mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-22 12:05:11 +00:00
Additional synchronization fixes for end cutscene.
This commit is contained in:
parent
469fa2ff33
commit
f5df807a0c
8 changed files with 223 additions and 93 deletions
|
@ -370,6 +370,11 @@ struct MarioState
|
|||
/*????*/ u8 isSnoring;
|
||||
/*????*/ struct Object* bubbleObj;
|
||||
/*????*/ u8 freeze;
|
||||
|
||||
// Variables for a spline curve animation (used for the flight path in the grand star cutscene)
|
||||
/*????*/ Vec4s* splineKeyframe;
|
||||
/*????*/ float splineKeyframeFraction;
|
||||
/*????*/ int splineState;
|
||||
};
|
||||
|
||||
#define PLAY_MODE_NORMAL 0
|
||||
|
|
|
@ -7,11 +7,6 @@
|
|||
|
||||
#include "trig_tables.inc.c"
|
||||
|
||||
// Variables for a spline curve animation (used for the flight path in the grand star cutscene)
|
||||
Vec4s *gSplineKeyframe;
|
||||
float gSplineKeyframeFraction;
|
||||
int gSplineState;
|
||||
|
||||
// These functions have bogus return values.
|
||||
// Disable the compiler warning.
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -824,14 +819,14 @@ f32 atan2f(f32 y, f32 x) {
|
|||
* [0, 0, 0, 0, 1, 2, ... n-1, n, n, n, n]
|
||||
* TODO: verify the classification of the spline / figure out how polynomials were computed
|
||||
*/
|
||||
void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c) {
|
||||
void spline_get_weights(struct MarioState* m, Vec4f result, f32 t, UNUSED s32 c) {
|
||||
f32 tinv = 1 - t;
|
||||
f32 tinv2 = tinv * tinv;
|
||||
f32 tinv3 = tinv2 * tinv;
|
||||
f32 t2 = t * t;
|
||||
f32 t3 = t2 * t;
|
||||
|
||||
switch (gSplineState) {
|
||||
switch (m->splineState) {
|
||||
case CURVE_BEGIN_1:
|
||||
result[0] = tinv3;
|
||||
result[1] = t3 * 1.75f - t2 * 4.5f + t * 3.0f;
|
||||
|
@ -873,10 +868,10 @@ void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c) {
|
|||
* The array should end with three entries with s=0 (infinite keyframe duration).
|
||||
* That's because the spline has a 3rd degree polynomial, so it looks 3 points ahead.
|
||||
*/
|
||||
void anim_spline_init(Vec4s *keyFrames) {
|
||||
gSplineKeyframe = keyFrames;
|
||||
gSplineKeyframeFraction = 0;
|
||||
gSplineState = 1;
|
||||
void anim_spline_init(struct MarioState* m, Vec4s *keyFrames) {
|
||||
m->splineKeyframe = keyFrames;
|
||||
m->splineKeyframeFraction = 0;
|
||||
m->splineState = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -884,33 +879,33 @@ void anim_spline_init(Vec4s *keyFrames) {
|
|||
* anim_spline_init should be called before polling for vectors.
|
||||
* Returns TRUE when the last point is reached, FALSE otherwise.
|
||||
*/
|
||||
s32 anim_spline_poll(Vec3f result) {
|
||||
s32 anim_spline_poll(struct MarioState* m, Vec3f result) {
|
||||
Vec4f weights;
|
||||
s32 i;
|
||||
s32 hasEnded = FALSE;
|
||||
|
||||
vec3f_copy(result, gVec3fZero);
|
||||
spline_get_weights(weights, gSplineKeyframeFraction, gSplineState);
|
||||
spline_get_weights(m, weights, m->splineKeyframeFraction, m->splineState);
|
||||
for (i = 0; i < 4; i++) {
|
||||
result[0] += weights[i] * gSplineKeyframe[i][1];
|
||||
result[1] += weights[i] * gSplineKeyframe[i][2];
|
||||
result[2] += weights[i] * gSplineKeyframe[i][3];
|
||||
result[0] += weights[i] * m->splineKeyframe[i][1];
|
||||
result[1] += weights[i] * m->splineKeyframe[i][2];
|
||||
result[2] += weights[i] * m->splineKeyframe[i][3];
|
||||
}
|
||||
|
||||
if ((gSplineKeyframeFraction += gSplineKeyframe[0][0] / 1000.0f) >= 1) {
|
||||
gSplineKeyframe++;
|
||||
gSplineKeyframeFraction--;
|
||||
switch (gSplineState) {
|
||||
if ((m->splineKeyframeFraction += m->splineKeyframe[0][0] / 1000.0f) >= 1) {
|
||||
m->splineKeyframe++;
|
||||
m->splineKeyframeFraction--;
|
||||
switch (m->splineState) {
|
||||
case CURVE_END_2:
|
||||
hasEnded = TRUE;
|
||||
break;
|
||||
case CURVE_MIDDLE:
|
||||
if (gSplineKeyframe[2][0] == 0) {
|
||||
gSplineState = CURVE_END_1;
|
||||
if (m->splineKeyframe[2][0] == 0) {
|
||||
m->splineState = CURVE_END_1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gSplineState++;
|
||||
m->splineState++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,8 +76,8 @@ s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec);
|
|||
f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec);
|
||||
s16 atan2s(f32 y, f32 x);
|
||||
f32 atan2f(f32 a, f32 b);
|
||||
void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c);
|
||||
void anim_spline_init(Vec4s *keyFrames);
|
||||
s32 anim_spline_poll(Vec3f result);
|
||||
void spline_get_weights(struct MarioState* m, Vec4f result, f32 t, UNUSED s32 c);
|
||||
void anim_spline_init(struct MarioState* m, Vec4s *keyFrames);
|
||||
s32 anim_spline_poll(struct MarioState* m, Vec3f result);
|
||||
|
||||
#endif // MATH_UTIL_H
|
||||
|
|
|
@ -68,6 +68,9 @@ void bhv_grand_star_loop(void) {
|
|||
} else {
|
||||
cur_obj_become_tangible();
|
||||
if (o->oInteractStatus & INT_STATUS_INTERACTED) {
|
||||
if (gMarioStates[0].action != ACT_JUMBO_STAR_CUTSCENE) {
|
||||
set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0);
|
||||
}
|
||||
obj_mark_for_deletion(o);
|
||||
o->oInteractStatus = 0;
|
||||
}
|
||||
|
|
|
@ -1228,6 +1228,7 @@ u8 player_is_sliding(struct MarioState* m) {
|
|||
|
||||
u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object* o) {
|
||||
if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; }
|
||||
if (m->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; }
|
||||
|
||||
struct MarioState* m2 = NULL;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
|
@ -1237,6 +1238,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
|
|||
}
|
||||
}
|
||||
if (m2 == NULL) { return FALSE; }
|
||||
if (m2->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; }
|
||||
|
||||
// don't do further interactions if we've hopped on top
|
||||
if (resolve_player_collision(m, m2)) {
|
||||
|
|
|
@ -1940,6 +1940,11 @@ static s32 act_intro_cutscene(struct MarioState *m) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void jumbo_star_offset(struct MarioState* m) {
|
||||
m->pos[0] += 300.0f * sins(m->faceAngle[1] + 0x4000 * m->playerIndex);
|
||||
m->pos[2] += 300.0f * coss(m->faceAngle[1] + 0x4000 * m->playerIndex);
|
||||
}
|
||||
|
||||
// jumbo star cutscene: Mario lands after grabbing the jumbo star
|
||||
static void jumbo_star_cutscene_falling(struct MarioState *m) {
|
||||
if (m->actionState == 0) {
|
||||
|
@ -1947,7 +1952,7 @@ static void jumbo_star_cutscene_falling(struct MarioState *m) {
|
|||
m->flags |= (MARIO_WING_CAP | MARIO_CAP_ON_HEAD);
|
||||
|
||||
m->faceAngle[1] = -0x8000;
|
||||
m->pos[0] = 0.0f;
|
||||
m->pos[0] = 100.0f * m->playerIndex;
|
||||
m->pos[2] = 0.0f;
|
||||
|
||||
mario_set_forward_vel(m, 0.0f);
|
||||
|
@ -2011,6 +2016,8 @@ static s32 jumbo_star_cutscene_taking_off(struct MarioState *m) {
|
|||
}
|
||||
|
||||
vec3f_set(m->pos, 0.0f, 307.0, marioObj->rawData.asF32[0x22]);
|
||||
m->pos[0] += 100.0f * m->playerIndex;
|
||||
|
||||
update_mario_pos_for_anim(m);
|
||||
vec3f_copy(marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
|
||||
|
@ -2033,15 +2040,19 @@ static s32 jumbo_star_cutscene_flying(struct MarioState *m) {
|
|||
switch (m->actionState) {
|
||||
case 0:
|
||||
set_mario_animation(m, MARIO_ANIM_WING_CAP_FLY);
|
||||
anim_spline_init(sJumboStarKeyframes);
|
||||
anim_spline_init(m, sJumboStarKeyframes);
|
||||
m->actionState++;
|
||||
// fall through
|
||||
case 1:
|
||||
if (anim_spline_poll(targetPos)) {
|
||||
if (anim_spline_poll(m, targetPos)) {
|
||||
// does this twice
|
||||
set_mario_action(m, ACT_FREEFALL, 0);
|
||||
m->actionState++;
|
||||
} else {
|
||||
targetPos[0] += 100.0f * m->playerIndex;
|
||||
float heightScalar = min(m->actionTimer / 30.0f, 1.0f);
|
||||
targetPos[1] -= 100.0f * m->playerIndex * heightScalar;
|
||||
|
||||
targetDX = targetPos[0] - m->pos[0];
|
||||
targetDY = targetPos[1] - m->pos[1];
|
||||
targetDZ = targetPos[2] - m->pos[2];
|
||||
|
@ -2064,7 +2075,7 @@ static s32 jumbo_star_cutscene_flying(struct MarioState *m) {
|
|||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
m->particleFlags |= PARTICLE_SPARKLES;
|
||||
|
||||
if (m->actionTimer++ == 500) {
|
||||
if (m->actionTimer++ == 500 && m->playerIndex == 0) {
|
||||
level_trigger_warp(m, WARP_OP_CREDITS_START);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,15 +2,23 @@
|
|||
#include "game/level_update.h"
|
||||
#include "game/camera.h"
|
||||
#include "pc/network/network.h"
|
||||
#include "game/mario.h"
|
||||
#include "sm64.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static u8 warpToLevel = LEVEL_CCM;
|
||||
|
||||
#define SCANCODE_0 0x0B
|
||||
#define SCANCODE_1 0x02
|
||||
#define SCANCODE_2 0x03
|
||||
#define SCANCODE_3 0x04
|
||||
#define SCANCODE_4 0x05
|
||||
#define SCANCODE_5 0x06
|
||||
#define SCANCODE_6 0x07
|
||||
#define SCANCODE_7 0x08
|
||||
#define SCANCODE_8 0x09
|
||||
#define SCANCODE_9 0x0A
|
||||
|
||||
static void debug_breakpoint_here(void) {
|
||||
// create easy breakpoint position for debugging
|
||||
|
@ -92,6 +100,10 @@ static void debug_warp_area() {
|
|||
}
|
||||
}
|
||||
|
||||
static void debug_grand_star(void) {
|
||||
set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0);
|
||||
}
|
||||
|
||||
static void debug_suicide(void) {
|
||||
gMarioStates[0].hurtCounter = 31;
|
||||
}
|
||||
|
@ -103,6 +115,7 @@ void debug_keyboard_on_key_down(int scancode) {
|
|||
#ifdef DEVELOPMENT
|
||||
case SCANCODE_6: debug_warp_level(warpToLevel); break;
|
||||
case SCANCODE_7: debug_warp_area(); break;
|
||||
case SCANCODE_9: debug_grand_star(); break;
|
||||
case SCANCODE_0: debug_suicide(); break;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -10,120 +10,221 @@
|
|||
#define SET_BIT(val, num) ((((u8)(val)) & 0x01) << (num));
|
||||
#define GET_BIT(val, num) (((val) >> (num)) & 0x01)
|
||||
|
||||
#pragma pack(1)
|
||||
struct PacketPlayerData {
|
||||
u32 rawData[80];
|
||||
struct Controller controller;
|
||||
s16 nodeFlags;
|
||||
|
||||
u16 input;
|
||||
u32 flags;
|
||||
u32 particleFlags;
|
||||
u32 action;
|
||||
u32 prevAction;
|
||||
u16 actionState;
|
||||
u16 actionTimer;
|
||||
u32 actionArg;
|
||||
f32 intendedMag;
|
||||
s16 intendedYaw;
|
||||
s16 invincTimer;
|
||||
u8 framesSinceA;
|
||||
u8 framesSinceB;
|
||||
u8 wallKickTimer;
|
||||
u8 doubleJumpTimer;
|
||||
Vec3s faceAngle;
|
||||
Vec3s angleVel;
|
||||
s16 slideYaw;
|
||||
s16 twirlYaw;
|
||||
Vec3f pos;
|
||||
Vec3f vel;
|
||||
f32 forwardVel;
|
||||
f32 slideVelX;
|
||||
f32 slideVelZ;
|
||||
s16 health;
|
||||
u8 squishTimer;
|
||||
f32 peakHeight;
|
||||
s16 currentRoom;
|
||||
|
||||
u8 customFlags;
|
||||
u32 heldSyncID;
|
||||
u32 heldBySyncID;
|
||||
};
|
||||
|
||||
static void read_packet_data(struct PacketPlayerData* data, struct MarioState* m) {
|
||||
u32 heldSyncID = (m->heldObj != NULL) ? m->heldObj->oSyncID : 0;
|
||||
u32 heldBySyncID = (m->heldByObj != NULL) ? m->heldByObj->oSyncID : 0;
|
||||
u8 customFlags = SET_BIT((m->freeze > 0), 0);
|
||||
|
||||
memcpy(data->rawData, m->marioObj->rawData.asU32, sizeof(u32) * 80);
|
||||
data->nodeFlags = m->marioObj->header.gfx.node.flags;
|
||||
data->controller = *m->controller;
|
||||
|
||||
data->input = m->input;
|
||||
data->flags = m->flags;
|
||||
data->particleFlags = m->particleFlags;
|
||||
data->action = m->action;
|
||||
data->prevAction = m->prevAction;
|
||||
data->actionState = m->actionState;
|
||||
data->actionTimer = m->actionTimer;
|
||||
data->actionArg = m->actionArg;
|
||||
data->intendedMag = m->intendedMag;
|
||||
data->intendedYaw = m->intendedYaw;
|
||||
data->invincTimer = m->invincTimer;
|
||||
data->framesSinceA = m->framesSinceA;
|
||||
data->framesSinceB = m->framesSinceB;
|
||||
data->wallKickTimer = m->wallKickTimer;
|
||||
data->doubleJumpTimer = m->doubleJumpTimer;
|
||||
memcpy(data->faceAngle, m->faceAngle, sizeof(s16) * 3);
|
||||
memcpy(data->angleVel, m->angleVel, sizeof(s16) * 3);
|
||||
data->slideYaw = m->slideYaw;
|
||||
data->twirlYaw = m->twirlYaw;
|
||||
memcpy(data->pos, m->pos, sizeof(f32) * 3);
|
||||
memcpy(data->vel, m->vel, sizeof(f32) * 3);
|
||||
data->forwardVel = m->forwardVel;
|
||||
data->slideVelX = m->slideVelX;
|
||||
data->slideVelZ = m->slideVelZ;
|
||||
data->health = m->health;
|
||||
data->squishTimer = m->squishTimer;
|
||||
data->peakHeight = m->peakHeight;
|
||||
data->currentRoom = m->currentRoom;
|
||||
|
||||
data->customFlags = customFlags;
|
||||
data->heldSyncID = heldSyncID;
|
||||
data->heldBySyncID = heldBySyncID;
|
||||
}
|
||||
|
||||
static void write_packet_data(struct PacketPlayerData* data, struct MarioState* m,
|
||||
u8* customFlags, u32* heldSyncID, u32* heldBySyncID) {
|
||||
memcpy(m->marioObj->rawData.asU32, data->rawData, sizeof(u32) * 80);
|
||||
m->marioObj->header.gfx.node.flags = data->nodeFlags;
|
||||
*m->controller = data->controller;
|
||||
|
||||
m->input = data->input;
|
||||
m->flags = data->flags;
|
||||
m->particleFlags = data->particleFlags;
|
||||
m->action = data->action;
|
||||
m->prevAction = data->prevAction;
|
||||
m->actionState = data->actionState;
|
||||
m->actionTimer = data->actionTimer;
|
||||
m->actionArg = data->actionArg;
|
||||
m->intendedMag = data->intendedMag;
|
||||
m->intendedYaw = data->intendedYaw;
|
||||
m->invincTimer = data->invincTimer;
|
||||
m->framesSinceA = data->framesSinceA;
|
||||
m->framesSinceB = data->framesSinceB;
|
||||
m->wallKickTimer = data->wallKickTimer;
|
||||
m->doubleJumpTimer = data->doubleJumpTimer;
|
||||
memcpy(m->faceAngle, data->faceAngle, sizeof(s16) * 3);
|
||||
memcpy(m->angleVel, data->angleVel, sizeof(s16) * 3);
|
||||
m->slideYaw = data->slideYaw;
|
||||
m->twirlYaw = data->twirlYaw;
|
||||
memcpy(m->pos, data->pos, sizeof(f32) * 3);
|
||||
memcpy(m->vel, data->vel, sizeof(f32) * 3);
|
||||
m->forwardVel = data->forwardVel;
|
||||
m->slideVelX = data->slideVelX;
|
||||
m->slideVelZ = data->slideVelZ;
|
||||
m->health = data->health;
|
||||
m->squishTimer = data->squishTimer;
|
||||
m->peakHeight = data->peakHeight;
|
||||
m->currentRoom = data->currentRoom;
|
||||
|
||||
*customFlags = data->customFlags;
|
||||
*heldSyncID = data->heldSyncID;
|
||||
*heldBySyncID = data->heldBySyncID;
|
||||
}
|
||||
|
||||
void network_send_player(void) {
|
||||
if (gMarioStates[0].marioObj == NULL) { return; }
|
||||
u32 heldSyncID = (gMarioStates[0].heldObj != NULL)
|
||||
? gMarioStates[0].heldObj->oSyncID
|
||||
: 0;
|
||||
u32 heldBySyncID = (gMarioStates[0].heldByObj != NULL)
|
||||
? gMarioStates[0].heldByObj->oSyncID
|
||||
: 0;
|
||||
|
||||
u8 customFlags = SET_BIT((gMarioStates[0].freeze > 0), 0);
|
||||
struct PacketPlayerData data = { 0 };
|
||||
read_packet_data(&data, &gMarioStates[0]);
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_PLAYER, false);
|
||||
packet_write(&p, &gMarioStates[0], sizeof(u32) * 24);
|
||||
packet_write(&p, gMarioStates[0].controller, 20);
|
||||
packet_write(&p, gMarioStates[0].marioObj->rawData.asU32, sizeof(u32) * 80);
|
||||
packet_write(&p, &gMarioStates[0].health, sizeof(s16));
|
||||
packet_write(&p, &gMarioStates[0].marioObj->header.gfx.node.flags, sizeof(s16));
|
||||
packet_write(&p, &gMarioStates[0].actionState, sizeof(u16));
|
||||
packet_write(&p, &gMarioStates[0].actionTimer, sizeof(u16));
|
||||
packet_write(&p, &gMarioStates[0].actionArg, sizeof(u32));
|
||||
packet_write(&p, &gMarioStates[0].currentRoom, sizeof(s16));
|
||||
packet_write(&p, &gMarioStates[0].squishTimer, sizeof(u8));
|
||||
packet_write(&p, &gMarioStates[0].peakHeight, sizeof(f32));
|
||||
packet_write(&p, &customFlags, sizeof(u8));
|
||||
packet_write(&p, &heldSyncID, sizeof(u32));
|
||||
packet_write(&p, &heldBySyncID, sizeof(u32));
|
||||
packet_write(&p, &data, sizeof(struct PacketPlayerData));
|
||||
network_send(&p);
|
||||
}
|
||||
|
||||
void network_receive_player(struct Packet* p) {
|
||||
if (gMarioStates[1].marioObj == NULL) { return; }
|
||||
struct MarioState* m = &gMarioStates[1];
|
||||
if (m == NULL || m->marioObj == NULL) { return; }
|
||||
|
||||
// save previous state
|
||||
u32 heldSyncID = 0;
|
||||
u32 heldBySyncID = 0;
|
||||
u16 playerIndex = gMarioStates[1].playerIndex;
|
||||
u8 customFlags = 0;
|
||||
u32 oldAction = gMarioStates[1].action;
|
||||
u16 oldActionState = gMarioStates[1].actionState;
|
||||
u16 oldActionArg = gMarioStates[1].actionArg;
|
||||
u32 oldBehParams = gMarioStates[1].marioObj->oBehParams;
|
||||
struct PacketPlayerData oldData = { 0 };
|
||||
read_packet_data(&oldData, m);
|
||||
u16 playerIndex = m->playerIndex;
|
||||
u32 oldBehParams = m->marioObj->oBehParams;
|
||||
|
||||
// load mario information from packet
|
||||
packet_read(p, &gMarioStates[1], sizeof(u32) * 24);
|
||||
packet_read(p, gMarioStates[1].controller, 20);
|
||||
packet_read(p, &gMarioStates[1].marioObj->rawData.asU32, sizeof(u32) * 80);
|
||||
packet_read(p, &gMarioStates[1].health, sizeof(s16));
|
||||
packet_read(p, &gMarioStates[1].marioObj->header.gfx.node.flags, sizeof(s16));
|
||||
packet_read(p, &gMarioStates[1].actionState, sizeof(u16));
|
||||
packet_read(p, &gMarioStates[1].actionTimer, sizeof(u16));
|
||||
packet_read(p, &gMarioStates[1].actionArg, sizeof(u32));
|
||||
packet_read(p, &gMarioStates[1].currentRoom, sizeof(s16));
|
||||
packet_read(p, &gMarioStates[1].squishTimer, sizeof(u8));
|
||||
packet_read(p, &gMarioStates[1].peakHeight, sizeof(f32));
|
||||
packet_read(p, &customFlags, sizeof(u8));
|
||||
packet_read(p, &heldSyncID, sizeof(u32));
|
||||
packet_read(p, &heldBySyncID, sizeof(u32));
|
||||
struct PacketPlayerData data = { 0 };
|
||||
packet_read(p, &data, sizeof(struct PacketPlayerData));
|
||||
|
||||
// check to see if we should just drop this packet
|
||||
if (oldData.action == ACT_JUMBO_STAR_CUTSCENE && data.action == ACT_JUMBO_STAR_CUTSCENE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// apply data from packet to mario state
|
||||
u32 heldSyncID = 0;
|
||||
u32 heldBySyncID = 0;
|
||||
u8 customFlags = 0;
|
||||
write_packet_data(&data, m, &customFlags, &heldSyncID, &heldBySyncID);
|
||||
|
||||
// read custom flags
|
||||
gMarioStates[1].freeze = GET_BIT(customFlags, 0);
|
||||
m->freeze = GET_BIT(customFlags, 0);
|
||||
|
||||
// reset player index
|
||||
gMarioStates[1].playerIndex = playerIndex;
|
||||
gMarioStates[1].marioObj->oBehParams = oldBehParams;
|
||||
m->playerIndex = playerIndex;
|
||||
m->marioObj->oBehParams = oldBehParams;
|
||||
|
||||
// reset mario sound play flag so that their jump sounds work
|
||||
if (gMarioStates[1].action != oldAction) {
|
||||
gMarioStates[1].flags &= ~(MARIO_ACTION_SOUND_PLAYED | MARIO_MARIO_SOUND_PLAYED);
|
||||
if (m->action != oldData.action) {
|
||||
m->flags &= ~(MARIO_ACTION_SOUND_PLAYED | MARIO_MARIO_SOUND_PLAYED);
|
||||
}
|
||||
|
||||
// find and set their held object
|
||||
if (heldSyncID != 0 && gSyncObjects[heldSyncID].o != NULL) {
|
||||
// TODO: do we have to move graphics nodes around to make this visible?
|
||||
struct Object* heldObj = gSyncObjects[heldSyncID].o;
|
||||
if (gMarioStates[0].heldObj == heldObj && gNetworkType == NT_CLIENT) { // two-player hack: needs priority
|
||||
if (m->heldObj == heldObj && gNetworkType == NT_CLIENT) { // two-player hack: needs priority
|
||||
mario_drop_held_object(&gMarioStates[0]);
|
||||
force_idle_state(&gMarioStates[0]);
|
||||
}
|
||||
gMarioStates[1].heldObj = heldObj;
|
||||
m->heldObj = heldObj;
|
||||
heldObj->oHeldState = HELD_HELD;
|
||||
heldObj->heldByPlayerIndex = 1;
|
||||
} else {
|
||||
gMarioStates[1].heldObj = NULL;
|
||||
m->heldObj = NULL;
|
||||
}
|
||||
|
||||
// find and set their held-by object
|
||||
if (heldBySyncID != 0 && gSyncObjects[heldBySyncID].o != NULL) {
|
||||
// TODO: do we have to move graphics nodes around to make this visible?
|
||||
gMarioStates[1].heldByObj = gSyncObjects[heldBySyncID].o;
|
||||
m->heldByObj = gSyncObjects[heldBySyncID].o;
|
||||
} else {
|
||||
gMarioStates[1].heldByObj = NULL;
|
||||
m->heldByObj = NULL;
|
||||
}
|
||||
|
||||
// jump kicking: restore action state, otherwise it won't play
|
||||
if (gMarioStates[1].action == ACT_JUMP_KICK) {
|
||||
gMarioStates[1].actionState = oldActionState;
|
||||
if (m->action == ACT_JUMP_KICK) {
|
||||
m->actionState = oldData.actionState;
|
||||
}
|
||||
|
||||
// punching:
|
||||
if ((gMarioStates[1].action == ACT_PUNCHING || gMarioStates[1].action == ACT_MOVE_PUNCHING)) {
|
||||
if ((m->action == ACT_PUNCHING || m->action == ACT_MOVE_PUNCHING)) {
|
||||
// play first punching sound, otherwise it will be missed
|
||||
if (gMarioStates[1].action != oldAction) {
|
||||
play_sound(SOUND_MARIO_PUNCH_YAH, gMarioStates[1].marioObj->header.gfx.cameraToObject);
|
||||
if (m->action != oldData.action) {
|
||||
play_sound(SOUND_MARIO_PUNCH_YAH, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
// make the first punch large, otherwise it will be missed
|
||||
if (gMarioStates[1].actionArg == 2 && oldActionArg == 1) {
|
||||
gMarioStates[1].marioBodyState->punchState = (0 << 6) | 4;
|
||||
if (m->actionArg == 2 && oldData.actionArg == 1) {
|
||||
m->marioBodyState->punchState = (0 << 6) | 4;
|
||||
}
|
||||
}
|
||||
|
||||
// action changed, reset timer
|
||||
if (gMarioStates[1].action != oldAction) {
|
||||
gMarioStates[1].actionTimer = 0;
|
||||
if (m->action != oldData.action) {
|
||||
m->actionTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue