Synchronized King Bobomb

Tried to synchronize dialog stuff, it's way too much of a mess to do
This commit is contained in:
MysterD 2020-08-08 17:13:11 -07:00
parent 4b61f7212b
commit 7f5dec337e
36 changed files with 291 additions and 217 deletions

View file

@ -3952,6 +3952,7 @@
<ClCompile Include="..\src\pc\network\packets\packet_player.c" />
<ClCompile Include="..\src\pc\network\packets\packet_read_write.c" />
<ClCompile Include="..\src\pc\network\packets\packet_reliable.c" />
<ClCompile Include="..\src\pc\network\packets\packet_spawn_objects.c" />
<ClCompile Include="..\src\pc\pc_main.c" />
<ClCompile Include="..\src\pc\platform.c" />
<ClCompile Include="..\src\pc\ultra_reimplementation.c" />

View file

@ -363,6 +363,7 @@ struct MarioState
/*0xBC*/ f32 peakHeight;
/*0xC0*/ f32 quicksandDepth;
/*0xC4*/ f32 unkC4;
/*0xC8*/ struct Object *heldByObj;
};
#define PLAY_MODE_NORMAL 0

View file

@ -350,7 +350,7 @@ void bobomb_buddy_cannon_dialog(s16 dialogFirstText, s16 dialogSecondText) {
break;
case BOBOMB_BUDDY_CANNON_STOP_TALKING:
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioStates[0], 0);
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
o->oBobombBuddyHasTalkedToMario = BOBOMB_BUDDY_HAS_TALKED;
@ -362,14 +362,14 @@ void bobomb_buddy_cannon_dialog(s16 dialogFirstText, s16 dialogSecondText) {
}
void bobomb_buddy_act_talk(void) {
if (set_mario_npc_dialog(1) == 2) {
if (set_mario_npc_dialog(&gMarioStates[0], 1) == 2) {
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
switch (o->oBobombBuddyRole) {
case BOBOMB_BUDDY_ROLE_ADVICE:
if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, o->oBehParams2ndByte)
!= BOBOMB_BUDDY_BP_STYPE_GENERIC) {
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioStates[0], 0);
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
o->oBobombBuddyHasTalkedToMario = BOBOMB_BUDDY_HAS_TALKED;

View file

@ -464,7 +464,7 @@ static void boo_act_4(void) {
dialogID = DIALOG_107;
}
if (cur_obj_update_dialog(2, 2, dialogID, 0)) {
if (cur_obj_update_dialog(&gMarioState[0], 2, 2, dialogID, 0)) {
create_sound_spawner(SOUND_OBJ_DYING_ENEMY1);
obj_mark_for_deletion(o);

View file

@ -833,7 +833,7 @@ s32 bowser_dead_not_bits_end(void) {
func_8031FFB4(SEQ_PLAYER_LEVEL, 60, 40);
o->oBowserUnkF8++;
}
if (cur_obj_update_dialog(2, 18, sBowserDefeatedDialogText[o->oBehParams2ndByte], 0)) {
if (cur_obj_update_dialog(&gMarioState[0], 2, 18, sBowserDefeatedDialogText[o->oBehParams2ndByte], 0)) {
o->oBowserUnkF8++;
cur_obj_play_sound_2(SOUND_GENERAL2_BOWSER_EXPLODE);
sequence_player_unlower(SEQ_PLAYER_LEVEL, 60);
@ -843,7 +843,7 @@ s32 bowser_dead_not_bits_end(void) {
bowser_dead_hide();
spawn_triangle_break_particles(20, 116, 1.0f, 0);
bowser_spawn_grand_star_key();
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
ret = 1;
}
return ret;
@ -862,7 +862,7 @@ s32 bowser_dead_bits_end(void) {
func_8031FFB4(SEQ_PLAYER_LEVEL, 60, 40);
o->oBowserUnkF8++;
}
if (cur_obj_update_dialog(2, 18, dialogID, 0)) {
if (cur_obj_update_dialog(&gMarioState[0], 2, 18, dialogID, 0)) {
cur_obj_set_model(MODEL_BOWSER2);
sequence_player_unlower(SEQ_PLAYER_LEVEL, 60);
sequence_player_fade_out(0, 1);

View file

@ -32,7 +32,7 @@ static void camera_lakitu_intro_act_trigger_cutscene(void) {
&& gMarioObject->oPosZ > -2000.0f && gMarioObject->oPosZ < -177.0f
&& gMarioObject->oPosZ < -177.0f) // always double check your conditions
{
if (set_mario_npc_dialog(2) == 1) {
if (set_mario_npc_dialog(&gMarioState[0], 2) == 1) {
o->oAction = CAMERA_LAKITU_INTRO_ACT_SPAWN_CLOUD;
}
}
@ -42,7 +42,7 @@ static void camera_lakitu_intro_act_trigger_cutscene(void) {
* Warp up into the air and spawn cloud, then enter the TODO action.
*/
static void camera_lakitu_intro_act_spawn_cloud(void) {
if (set_mario_npc_dialog(2) == 2) {
if (set_mario_npc_dialog(&gMarioState[0], 2) == 2) {
o->oAction = CAMERA_LAKITU_INTRO_ACT_UNK2;
o->oPosX = 1800.0f;
@ -115,7 +115,7 @@ static void camera_lakitu_intro_act_show_dialog(void) {
}
}
}
} else if (cur_obj_update_dialog_with_cutscene(2, DIALOG_UNK2_FLAG_0, CUTSCENE_DIALOG, DIALOG_034) != 0) {
} else if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, DIALOG_UNK2_FLAG_0, CUTSCENE_DIALOG, DIALOG_034) != 0) {
o->oCameraLakituFinishedDialog = TRUE;
}
}

View file

@ -34,7 +34,7 @@ void cap_switch_act_2(void) {
queue_rumble_data(5, 80);
}
} else {
sp1C = cur_obj_update_dialog_with_cutscene(1, 0x0C, CUTSCENE_CAP_SWITCH_PRESS, 0);
sp1C = cur_obj_update_dialog_with_cutscene(&gMarioState[0], 1, 0x0C, CUTSCENE_CAP_SWITCH_PRESS, 0);
if (sp1C)
o->oAction = 3;
}

View file

@ -270,7 +270,7 @@ static void chain_chomp_released_trigger_cutscene(void) {
//! Can delay this if we get into a cutscene-unfriendly action after the
// last post ground pound and before this
if (set_mario_npc_dialog(2) == 2 && (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND)
if (set_mario_npc_dialog(&gMarioState[0], 2) == 2 && (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND)
&& cutscene_object(CUTSCENE_STAR_SPAWN, o) == 1) {
o->oChainChompReleaseStatus = CHAIN_CHOMP_RELEASED_LUNGE_AROUND;
o->oTimer = 0;
@ -359,7 +359,7 @@ static void chain_chomp_released_jump_away(void) {
*/
static void chain_chomp_released_end_cutscene(void) {
if (cutscene_object(CUTSCENE_STAR_SPAWN, o) == -1) {
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
o->oAction = CHAIN_CHOMP_ACT_UNLOAD_CHAIN;
}
}

View file

@ -1,29 +1,34 @@
// chuckya.c.inc
void common_anchor_mario_behavior(f32 sp28, f32 sp2C, s32 sp30) {
switch (o->parentObj->oChuckyaUnk88) {
case 0:
break;
case 1:
obj_set_gfx_pos_at_obj_pos(gMarioObject, o);
break;
case 2:
gMarioObject->oInteractStatus |= (sp30 + INT_STATUS_MARIO_UNK2);
gMarioStates->forwardVel = sp28;
gMarioStates->vel[1] = sp2C;
o->parentObj->oChuckyaUnk88 = 0;
break;
case 3:
gMarioObject->oInteractStatus |=
(INT_STATUS_MARIO_UNK2 + INT_STATUS_MARIO_UNK6); // loads 2 interactions at once?
gMarioStates->forwardVel = 10.0f;
gMarioStates->vel[1] = 10.0f;
o->parentObj->oChuckyaUnk88 = 0;
break;
for (int i = 0; i < MAX_PLAYERS; i++) {
struct MarioState* marioState = &gMarioStates[i];
struct Object* player = gMarioStates[i].marioObj;
if (marioState->heldByObj != o->parentObj && marioState->heldByObj != o) { continue; }
switch (o->parentObj->oChuckyaUnk88) {
case 0:
break;
case 1:
obj_set_gfx_pos_at_obj_pos(player, o);
break;
case 2:
player->oInteractStatus |= (sp30 + INT_STATUS_MARIO_UNK2);
marioState->forwardVel = sp28;
marioState->vel[1] = sp2C;
o->parentObj->oChuckyaUnk88 = 0;
break;
case 3:
player->oInteractStatus |=
(INT_STATUS_MARIO_UNK2 + INT_STATUS_MARIO_UNK6); // loads 2 interactions at once?
marioState->forwardVel = 10.0f;
marioState->vel[1] = 10.0f;
o->parentObj->oChuckyaUnk88 = 0;
break;
}
o->oMoveAngleYaw = o->parentObj->oMoveAngleYaw;
if (o->parentObj->activeFlags == ACTIVE_FLAG_DEACTIVATED)
obj_mark_for_deletion(o);
}
o->oMoveAngleYaw = o->parentObj->oMoveAngleYaw;
if (o->parentObj->activeFlags == ACTIVE_FLAG_DEACTIVATED)
obj_mark_for_deletion(o);
}
void bhv_chuckya_anchor_mario_loop(void) {

View file

@ -68,7 +68,7 @@ void dorrie_act_lower_head(void) {
if (o->oTimer > 150) {
dorrie_begin_head_raise(FALSE);
} else if (gMarioObject->platform == o) {
if (o->oDorrieForwardDistToMario > 830.0f && set_mario_npc_dialog(2) == 1) {
if (o->oDorrieForwardDistToMario > 830.0f && set_mario_npc_dialog(&gMarioState[0], 2) == 1) {
dorrie_begin_head_raise(TRUE);
} else if (o->oDorrieForwardDistToMario > 320.0f) {
o->oTimer = 0;
@ -77,7 +77,7 @@ void dorrie_act_lower_head(void) {
#else
if (gMarioObject->platform == o) {
if (o->oDorrieOffsetY == -17.0f && o->oDorrieForwardDistToMario > 780.0f
&& set_mario_npc_dialog(2) == 1) {
&& set_mario_npc_dialog(&gMarioState[0], 2) == 1) {
dorrie_begin_head_raise(TRUE);
} else if (o->oDorrieForwardDistToMario > 320.0f) {
o->oTimer = 0;
@ -97,10 +97,10 @@ void dorrie_act_raise_head(void) {
if (cur_obj_check_if_near_animation_end()) {
o->oAction = DORRIE_ACT_MOVE;
} else if (o->oDorrieLiftingMario && o->header.gfx.unk38.animFrame < 74) {
if (set_mario_npc_dialog(2) == 2) {
if (set_mario_npc_dialog(&gMarioState[0], 2) == 2) {
o->oDorrieHeadRaiseSpeed += 0x1CC;
if (cur_obj_check_anim_frame(73)) {
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
}
dorrie_raise_head();
} else {

View file

@ -47,7 +47,7 @@ static void eyerok_boss_act_wake_up(void) {
o->oSubAction += 1;
}
if (o->oEyerokBossUnk110 == 0.0f && mario_ready_to_speak() != 0) {
if (o->oEyerokBossUnk110 == 0.0f && mario_ready_to_speak(&gMarioStates[0]) != 0) {
o->oAction = EYEROK_BOSS_ACT_SHOW_INTRO_TEXT;
} else if (o->oTimer > 150) {
if (approach_f32_ptr(&o->oEyerokBossUnk110, 0.0f, 10.0f)) {
@ -63,7 +63,7 @@ static void eyerok_boss_act_wake_up(void) {
}
static void eyerok_boss_act_show_intro_text(void) {
if (cur_obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG, DIALOG_117)) {
if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 0, CUTSCENE_DIALOG, DIALOG_117)) {
o->oAction = EYEROK_BOSS_ACT_FIGHT;
}
}
@ -117,7 +117,7 @@ static void eyerok_boss_act_fight(void) {
static void eyerok_boss_act_die(void) {
if (o->oTimer == 60) {
if (cur_obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG, DIALOG_118)) {
if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 0, CUTSCENE_DIALOG, DIALOG_118)) {
spawn_default_star(0.0f, -900.0f, -3700.0f);
} else {
o->oTimer -= 1;

View file

@ -51,7 +51,7 @@ void bhv_grand_star_loop(void) {
o->oPosY = o->oHomeY + 200.0f;
grand_star_zero_velocity();
gObjCutsceneDone = 1;
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
o->oAction++;
o->oInteractStatus = 0;
cur_obj_play_sound_2(SOUND_GENERAL_GRAND_STAR_JUMP);

View file

@ -254,8 +254,8 @@ void bhv_hoot_loop(void) {
case HOOT_AVAIL_WANTS_TO_TALK:
hoot_awake_loop();
if (set_mario_npc_dialog(2) == 2 && cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_044)) {
set_mario_npc_dialog(0);
if (set_mario_npc_dialog(&gMarioState[0], 2) == 2 && cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_044)) {
set_mario_npc_dialog(&gMarioState[0], 0);
cur_obj_become_tangible();

View file

@ -1,5 +1,22 @@
// king_bobomb.c.inc
struct MarioState* king_bobomb_nearest_mario_state() {
struct MarioState* nearest = NULL;
f32 nearestDist = 0;
for (int i = 0; i < MAX_PLAYERS; i++) {
float ydiff = (o->oPosY - gMarioStates[i].marioObj->oPosY);
if (ydiff >= 1200) { continue; }
float dist = dist_between_objects(o, gMarioState[i].marioObj);
if (nearest == NULL || dist < nearestDist) {
nearest = &gMarioState[i];
nearestDist = dist;
}
}
return nearest;
}
// Copy of geo_update_projectile_pos_from_parent
Gfx *geo_update_held_mario_pos(s32 run, UNUSED struct GraphNode *node, Mat4 mtx) {
Mat4 sp20;
@ -20,6 +37,16 @@ void bhv_bobomb_anchor_mario_loop(void) {
common_anchor_mario_behavior(50.0f, 50.0f, 64);
}
u8 cur_obj_update_dialog_with_cutscene_hack(s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID) {
// disable dialogs, too weird to sync
return TRUE;
/*if (nearest_mario_state_to_object(o) == &gMarioStates[0]) {
cur_obj_update_dialog_with_cutscene(&gMarioState[0], actionArg, dialogFlags, cutsceneTable, dialogID);
} else {
return FALSE;
}*/
}
void king_bobomb_act_0(void) {
#ifndef VERSION_JP
o->oForwardVel = 0;
@ -31,21 +58,21 @@ void king_bobomb_act_0(void) {
cur_obj_init_animation_with_sound(5);
cur_obj_set_pos_to_home();
o->oHealth = 3;
if (cur_obj_can_mario_activate_textbox_2(500.0f, 100.0f)) {
if (nearest_mario_state_to_object(o) == &gMarioStates[0] && cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 500.0f, 100.0f)) {
o->oSubAction++;
func_8031FFB4(SEQ_PLAYER_LEVEL, 60, 40);
}
} else if (cur_obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG, DIALOG_017)) {
} else if (cur_obj_update_dialog_with_cutscene_hack(2, 1, CUTSCENE_DIALOG, DIALOG_017)) {
o->oAction = 2;
o->oFlags |= OBJ_FLAG_HOLDABLE;
}
}
int mario_is_far_below_object(f32 arg0) {
if (arg0 < o->oPosY - gMarioObject->oPosY)
return 1;
else
return 0;
for (int i = 0; i < MAX_PLAYERS; i++) {
if (arg0 >= o->oPosY - gMarioStates[i].marioObj->oPosY) { return FALSE; }
}
return TRUE;
}
void king_bobomb_act_2(void) {
@ -67,7 +94,11 @@ void king_bobomb_act_2(void) {
cur_obj_init_animation_with_sound(11);
if (o->oKingBobombUnk108 == 0) {
o->oForwardVel = 3.0f;
cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x100);
struct MarioState* marioState = king_bobomb_nearest_mario_state();
if (marioState != NULL) {
int angleToPlayer = obj_angle_to_object(o, marioState->marioObj);
cur_obj_rotate_yaw_toward(angleToPlayer, 0x100);
}
} else {
o->oForwardVel = 0.0f;
o->oKingBobombUnk108--;
@ -127,9 +158,17 @@ void king_bobomb_act_1(void) {
o->oForwardVel = 0;
o->oVelY = 0;
cur_obj_init_animation_with_sound(11);
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oAngleToMario, 512);
if (o->oDistanceToMario < 2500.0f)
struct MarioState* marioState = king_bobomb_nearest_mario_state();
int distanceToPlayer = (marioState != NULL) ? dist_between_objects(o, marioState->marioObj) : 3000;
if (marioState != NULL) {
int angleToPlayer = obj_angle_to_object(o, marioState->marioObj);
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, angleToPlayer, 512);
}
if (distanceToPlayer < 2500.0f)
o->oAction = 2;
if (mario_is_far_below_object(1200.0f)) {
o->oAction = 0;
stop_background_music(SEQUENCE_ARGS(4, SEQ_EVENT_BOSS));
@ -162,15 +201,20 @@ void king_bobomb_act_6(void) {
}
} else {
cur_obj_init_animation_with_sound(11);
if (cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x800) == 1)
o->oAction = 2;
struct MarioState* marioState = king_bobomb_nearest_mario_state();
if (marioState != NULL) {
int angleToPlayer = obj_angle_to_object(o, marioState->marioObj);
if (cur_obj_rotate_yaw_toward(angleToPlayer, 0x800) == 1) {
o->oAction = 2;
}
}
}
}
}
void king_bobomb_act_7(void) {
cur_obj_init_animation_with_sound(2);
if (cur_obj_update_dialog_with_cutscene(2, 2, CUTSCENE_DIALOG, DIALOG_116)) {
if (cur_obj_update_dialog_with_cutscene_hack(2, 2, CUTSCENE_DIALOG, DIALOG_116)) {
create_sound_spawner(SOUND_OBJ_KING_WHOMP_DEATH);
cur_obj_hide();
cur_obj_become_intangible();
@ -258,11 +302,11 @@ void king_bobomb_act_5(void) { // bobomb returns home
o->oAction = 0;
stop_background_music(SEQUENCE_ARGS(4, SEQ_EVENT_BOSS));
}
if (cur_obj_can_mario_activate_textbox_2(500.0f, 100.0f))
if (nearest_mario_state_to_object(o) == &gMarioStates[0] && cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 500.0f, 100.0f))
o->oSubAction++;
break;
case 4:
if (cur_obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG, DIALOG_128))
if (cur_obj_update_dialog_with_cutscene_hack(2, 1, CUTSCENE_DIALOG, DIALOG_128))
o->oAction = 2;
break;
}
@ -296,7 +340,9 @@ void king_bobomb_move(void) {
cur_obj_call_action_function(sKingBobombActions);
exec_anim_sound_state(sKingBobombSoundStates);
#ifndef NODRAWINGDISTANCE
if (o->oDistanceToMario < 5000.0f)
struct Object* player = nearest_player_to_object(o);
int distanceToPlayer = dist_between_objects(o, player);
if (distanceToPlayer < 5000.0f)
#endif
cur_obj_enable_rendering();
#ifndef NODRAWINGDISTANCE
@ -306,6 +352,15 @@ void king_bobomb_move(void) {
}
void bhv_king_bobomb_loop(void) {
if (o->oSyncID == 0) {
network_init_object(o, 4000.0f);
network_init_object_field(o, &o->oKingBobombUnk88);
network_init_object_field(o, &o->oFlags);
network_init_object_field(o, &o->oHealth);
network_init_object_field(o, &o->oDialogState);
network_init_object_field(o, &o->oDialogResponse);
}
f32 sp34 = 20.0f;
f32 sp30 = 50.0f;
UNUSED u8 pad[8];

View file

@ -514,7 +514,7 @@ s32 obj_begin_race(s32 noTimer) {
}
// Unfreeze mario and disable time stop to begin the race
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
disable_time_stop_including_mario();
} else if (o->oTimer > 50) {
return TRUE;
@ -531,7 +531,7 @@ static void koopa_the_quick_act_wait_before_race(void) {
if (o->oKoopaTheQuickInitTextboxCooldown != 0) {
o->oKoopaTheQuickInitTextboxCooldown -= 1;
} else if (cur_obj_can_mario_activate_textbox_2(400.0f, 400.0f)) {
} else if (cur_obj_can_mario_activate_textbox_2(&gMarioState[0], 400.0f, 400.0f)) {
//! The next action doesn't execute until next frame, giving mario one
// frame where he can jump, and thus no longer be ready to speak.
// (On J, he has two frames and doing this enables time stop - see
@ -548,7 +548,7 @@ static void koopa_the_quick_act_wait_before_race(void) {
*/
static void koopa_the_quick_act_show_init_text(void) {
s32 response = obj_update_race_proposition_dialog(
sKoopaTheQuickProperties[o->oKoopaTheQuickRaceIndex].initText);
&gMarioStates[0], sKoopaTheQuickProperties[o->oKoopaTheQuickRaceIndex].initText);
UNUSED s32 unused;
if (response == 1) {
@ -744,7 +744,7 @@ static void koopa_the_quick_act_after_race(void) {
cur_obj_init_animation_with_sound(7);
if (o->parentObj->oKoopaRaceEndpointUnk100 == 0) {
if (cur_obj_can_mario_activate_textbox_2(400.0f, 400.0f)) {
if (cur_obj_can_mario_activate_textbox_2(&gMarioState[0], 400.0f, 400.0f)) {
stop_background_music(SEQUENCE_ARGS(4, SEQ_LEVEL_SLIDE));
// Determine which text to display
@ -767,7 +767,7 @@ static void koopa_the_quick_act_after_race(void) {
o->oFlags &= ~OBJ_FLAG_ACTIVE_FROM_AFAR;
}
} else if (o->parentObj->oKoopaRaceEndpointUnk100 > 0) {
s32 dialogResponse = cur_obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG, o->parentObj->oKoopaRaceEndpointUnk100);
s32 dialogResponse = cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 1, CUTSCENE_DIALOG, o->parentObj->oKoopaRaceEndpointUnk100);
if (dialogResponse != 0) {
o->parentObj->oKoopaRaceEndpointUnk100 = -1;
o->oTimer = 0;

View file

@ -239,13 +239,13 @@ void bhv_mips_held(void) {
else
dialogID = DIALOG_162;
if (set_mario_npc_dialog(1) == 2) {
if (set_mario_npc_dialog(&gMarioState[0], 1) == 2) {
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, dialogID)) {
o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY;
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
o->oMipsStarStatus = MIPS_STAR_STATUS_SHOULD_SPAWN_STAR;
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
}
}
}

View file

@ -19,7 +19,7 @@ void bhv_racing_penguin_init(void) {
static void racing_penguin_act_wait_for_mario(void) {
if (o->oTimer > o->oRacingPenguinInitTextCooldown && o->oPosY - gMarioObject->oPosY <= 0.0f
&& cur_obj_can_mario_activate_textbox_2(400.0f, 400.0f)) {
&& cur_obj_can_mario_activate_textbox_2(&gMarioState[0], 400.0f, 400.0f)) {
o->oAction = RACING_PENGUIN_ACT_SHOW_INIT_TEXT;
}
}
@ -28,7 +28,7 @@ static void racing_penguin_act_show_init_text(void) {
s32 response;
struct Object *child;
response = obj_update_race_proposition_dialog(sRacingPenguinData[o->oBehParams2ndByte].text);
response = obj_update_race_proposition_dialog(&gMarioStates[0], sRacingPenguinData[o->oBehParams2ndByte].text);
if (response == 1) {
child = cur_obj_nearest_object_with_behavior(bhvPenguinRaceFinishLine);
child->parentObj = o;
@ -122,7 +122,7 @@ static void racing_penguin_act_show_final_text(void) {
cur_obj_init_animation_with_sound(3);
o->oForwardVel = 0.0f;
if (cur_obj_can_mario_activate_textbox_2(400.0f, 400.0f)) {
if (cur_obj_can_mario_activate_textbox_2(&gMarioState[0], 400.0f, 400.0f)) {
if (o->oRacingPenguinMarioWon) {
if (o->oRacingPenguinMarioCheated) {
o->oRacingPenguinFinalTextbox = DIALOG_132;
@ -144,7 +144,7 @@ static void racing_penguin_act_show_final_text(void) {
o->oForwardVel = 4.0f;
}
} else if (o->oRacingPenguinFinalTextbox > 0) {
if ((textResult = cur_obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG, o->oRacingPenguinFinalTextbox)) != 0) {
if ((textResult = cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 1, CUTSCENE_DIALOG, o->oRacingPenguinFinalTextbox)) != 0) {
o->oRacingPenguinFinalTextbox = -1;
o->oTimer = 0;
}

View file

@ -15,13 +15,13 @@ void bhv_sl_snowman_wind_loop(void) {
// Check if Mario is within 1000 units of the center of the bridge, and ready to speak.
vec3f_copy_2(tempPos, &o->oPosX);
obj_set_pos(o, 1100, 3328, 1164); // Position is in the middle of the ice bridge
if (cur_obj_can_mario_activate_textbox(1000.0f, 30.0f, 0x7FFF))
if (cur_obj_can_mario_activate_textbox(&gMarioState[0], 1000.0f, 30.0f, 0x7FFF))
o->oSubAction++;
vec3f_copy_2(&o->oPosX, tempPos);
// Mario has come close, begin dialog.
} else if (o->oSubAction == SL_SNOWMAN_WIND_ACT_TALKING) {
if (cur_obj_update_dialog(2, 2, DIALOG_153, 0))
if (cur_obj_update_dialog(&gMarioState[0], 2, 2, DIALOG_153, 0))
o->oSubAction++;
// Blowing, spawn wind particles (SL_SNOWMAN_WIND_ACT_BLOWING)

View file

@ -124,12 +124,12 @@ void bhv_snowmans_bottom_loop(void) {
switch (o->oAction) {
case 0:
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 400) == 1
&& set_mario_npc_dialog(1) == 2) {
&& set_mario_npc_dialog(&gMarioState[0], 1) == 2) {
sp1E = cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_110);
if (sp1E) {
o->oForwardVel = 10.0f;
o->oAction = 1;
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
}
}
break;
@ -191,7 +191,7 @@ void bhv_snowmans_head_loop(void) {
switch (o->oAction) {
case 0:
if (trigger_obj_dialog_when_facing(&o->oSnowmansHeadUnkF4, DIALOG_109, 400.0f, 1))
if (trigger_obj_dialog_when_facing(&gMarioState[0], &o->oSnowmansHeadUnkF4, DIALOG_109, 400.0f, 1))
o->oAction = 1;
break;
@ -215,7 +215,7 @@ void bhv_snowmans_head_loop(void) {
break;
case 4:
if (trigger_obj_dialog_when_facing(&o->oSnowmansHeadUnkF4, DIALOG_111, 700.0f, 2)) {
if (trigger_obj_dialog_when_facing(&gMarioState[0], &o->oSnowmansHeadUnkF4, DIALOG_111, 700.0f, 2)) {
spawn_mist_particles();
spawn_default_star(-4700.0f, -1024.0f, 1890.0f);
o->oAction = 1;

View file

@ -54,7 +54,7 @@ void tuxies_mother_act_1(void) {
dialogID = DIALOG_058;
else
dialogID = DIALOG_059;
if (cur_obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG, dialogID)) {
if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 1, CUTSCENE_DIALOG, dialogID)) {
if (dialogID == DIALOG_058)
o->oSubAction = 1;
else
@ -112,12 +112,12 @@ void tuxies_mother_act_0(void) {
} else {
switch (o->oSubAction) {
case 0:
if (cur_obj_can_mario_activate_textbox_2(300.0f, 100.0f))
if (cur_obj_can_mario_activate_textbox_2(&gMarioState[0], 300.0f, 100.0f))
if (sp2C == 0)
o->oSubAction++;
break;
case 1:
if (cur_obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG, DIALOG_057))
if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 1, CUTSCENE_DIALOG, DIALOG_057))
o->oSubAction++;
break;
case 2:

View file

@ -374,7 +374,7 @@ void ukiki_act_go_to_cage(void) {
cur_obj_init_animation_with_sound(UKIKI_ANIM_JUMP_CLAP);
cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x400);
if (cur_obj_can_mario_activate_textbox(200.0f, 30.0f, 0x7FFF)) {
if (cur_obj_can_mario_activate_textbox(&gMarioState[0], 200.0f, 30.0f, 0x7FFF)) {
o->oSubAction++; // fallthrough
} else {
break;
@ -383,7 +383,7 @@ void ukiki_act_go_to_cage(void) {
case UKIKI_SUB_ACT_CAGE_TALK_TO_MARIO:
cur_obj_init_animation_with_sound(UKIKI_ANIM_HANDSTAND);
if (cur_obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG, DIALOG_080)) {
if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 3, 1, CUTSCENE_DIALOG, DIALOG_080)) {
o->oSubAction++;
}
break;
@ -516,7 +516,7 @@ void cage_ukiki_held_loop(void) {
if (o->oPosY - o->oHomeY > -100.0f) {
switch(o->oUkikiTextState) {
case UKIKI_TEXT_DEFAULT:
if (set_mario_npc_dialog(2) == 2) {
if (set_mario_npc_dialog(&gMarioState[0], 2) == 2) {
create_dialog_box_with_response(DIALOG_079);
o->oUkikiTextState = UKIKI_TEXT_CAGE_TEXTBOX;
}
@ -524,7 +524,7 @@ void cage_ukiki_held_loop(void) {
case UKIKI_TEXT_CAGE_TEXTBOX:
if (gDialogResponse != 0) {
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
if (gDialogResponse == 1) {
o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY;
o->oUkikiTextState = UKIKI_TEXT_GO_TO_CAGE;
@ -567,7 +567,7 @@ void hat_ukiki_held_loop(void) {
break;
case UKIKI_TEXT_STEAL_HAT:
if (cur_obj_update_dialog(2, 2, DIALOG_100, 0)) {
if (cur_obj_update_dialog(&gMarioState[0], 2, 2, DIALOG_100, 0)) {
o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY;
o->oUkikiTextState = UKIKI_TEXT_STOLE_HAT;
}
@ -577,9 +577,9 @@ void hat_ukiki_held_loop(void) {
break;
case UKIKI_TEXT_HAS_HAT:
if (cur_obj_update_dialog(2, 18, DIALOG_101, 0)) {
if (cur_obj_update_dialog(&gMarioState[0], 2, 18, DIALOG_101, 0)) {
mario_retrieve_cap();
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
o->oUkikiHasHat &= ~UKIKI_HAT_ON;
o->oUkikiTextState = UKIKI_TEXT_GAVE_HAT_BACK;
}

View file

@ -28,7 +28,7 @@ void whomp_act_0(void) {
cur_obj_set_pos_to_home();
o->oHealth = 3;
}
} else if (cur_obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG, DIALOG_114))
} else if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 1, CUTSCENE_DIALOG, DIALOG_114))
o->oAction = 2;
} else if (o->oDistanceToMario < 500.0f)
o->oAction = 1;
@ -209,7 +209,7 @@ void whomp_act_6(void) {
void whomp_act_8(void) {
if (o->oBehParams2ndByte != 0) {
if (cur_obj_update_dialog_with_cutscene(2, 2, CUTSCENE_DIALOG, DIALOG_115)) {
if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 2, CUTSCENE_DIALOG, DIALOG_115)) {
obj_set_angle(o, 0, 0, 0);
cur_obj_hide();
cur_obj_become_intangible();

View file

@ -228,7 +228,7 @@ static void wiggler_act_walk(void) {
// If Mario is positioned below the wiggler, assume he entered through the
// lower cave entrance, so don't display text.
if (gMarioObject->oPosY < o->oPosY || cur_obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG, DIALOG_150) != 0) {
if (gMarioObject->oPosY < o->oPosY || cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 0, CUTSCENE_DIALOG, DIALOG_150) != 0) {
o->oWigglerTextStatus = WIGGLER_TEXT_STATUS_COMPLETED_DIALOG;
}
} else {
@ -304,7 +304,7 @@ static void wiggler_act_jumped_on(void) {
// defeated) or go back to walking
if (o->header.gfx.scale[1] >= 4.0f) {
if (o->oTimer > 30) {
if (cur_obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG, attackText[o->oHealth - 2]) != 0) {
if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 2, 0, CUTSCENE_DIALOG, attackText[o->oHealth - 2]) != 0) {
// Because we don't want the wiggler to disappear after being
// defeated, we leave its health at 1
if (--o->oHealth == 1) {

View file

@ -75,7 +75,7 @@ void yoshi_idle_loop(void) {
void yoshi_talk_loop(void) {
if ((s16) o->oMoveAngleYaw == (s16) o->oAngleToMario) {
cur_obj_init_animation(0);
if (set_mario_npc_dialog(1) == 2) {
if (set_mario_npc_dialog(&gMarioState[0], 1) == 2) {
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_161)) {
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
@ -122,7 +122,7 @@ void yoshi_finish_jumping_and_despawn_loop(void) {
obj_move_xyz_using_fvel_and_yaw(o);
o->oVelY -= 2.0;
if (o->oPosY < 2100.0f) {
set_mario_npc_dialog(0);
set_mario_npc_dialog(&gMarioState[0], 0);
gObjCutsceneDone = TRUE;
sYoshiDead = 1;
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;

View file

@ -7062,7 +7062,7 @@ void copy_spline_segment(struct CutsceneSplinePoint dst[], struct CutsceneSpline
s16 cutscene_common_set_dialog_state(s32 state) {
s16 timer = gCutsceneTimer;
// If the dialog ended, return CUTSCENE_LOOP, which would end the cutscene shot
if (set_mario_npc_dialog(state) == 2) {
if (set_mario_npc_dialog(&gMarioState[0], state) == 2) {
timer = CUTSCENE_LOOP;
}
return timer;

View file

@ -726,6 +726,9 @@ s16 find_floor_slope(struct MarioState *m, s16 yawOffset) {
* Adjusts Mario's camera and sound based on his action status.
*/
void update_mario_sound_and_camera(struct MarioState *m) {
// only update for local player
if (m != &gMarioStates[0]) { return; }
u32 action = m->action;
s32 camPreset = m->area->camera->mode;
@ -1678,7 +1681,7 @@ void mario_update_hitbox_and_cap_model(struct MarioState *m) {
// this can be paused through to give continual invisibility. This leads to
// no interaction with objects.
if (gGlobalTimer & 1) {
gMarioState->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
}
}

View file

@ -652,14 +652,18 @@ s32 act_grabbed(struct MarioState *m) {
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_UNK2) {
s32 thrown = (m->marioObj->oInteractStatus & INT_STATUS_MARIO_UNK6) == 0;
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
if (m->usedObj != NULL) {
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
}
vec3f_copy(m->pos, m->marioObj->header.gfx.pos);
queue_rumble_data(5, 60);
m->heldByObj = NULL;
return set_mario_action(m, (m->forwardVel >= 0.0f) ? ACT_THROWN_FORWARD : ACT_THROWN_BACKWARD,
thrown);
}
if (m->usedObj != NULL) { m->heldByObj = m->usedObj; }
set_mario_animation(m, MARIO_ANIM_BEING_GRABBED);
return FALSE;
}

View file

@ -331,14 +331,14 @@ void cutscene_put_cap_on(struct MarioState *m) {
* 2: Mario mat not be riding a shell or be invulnerable.
* 3: Mario must not be in first person mode.
*/
s32 mario_ready_to_speak(void) {
u32 actionGroup = gMarioState->action & ACT_GROUP_MASK;
s32 mario_ready_to_speak(struct MarioState* m) {
u32 actionGroup = m->action & ACT_GROUP_MASK;
s32 isReadyToSpeak = FALSE;
if ((gMarioState->action == ACT_WAITING_FOR_DIALOG || actionGroup == ACT_GROUP_STATIONARY
if ((m->action == ACT_WAITING_FOR_DIALOG || actionGroup == ACT_GROUP_STATIONARY
|| actionGroup == ACT_GROUP_MOVING)
&& (!(gMarioState->action & (ACT_FLAG_RIDING_SHELL | ACT_FLAG_INVULNERABLE))
&& gMarioState->action != ACT_FIRST_PERSON)) {
&& (!(m->action & (ACT_FLAG_RIDING_SHELL | ACT_FLAG_INVULNERABLE))
&& m->action != ACT_FIRST_PERSON)) {
isReadyToSpeak = TRUE;
}
@ -351,24 +351,24 @@ s32 mario_ready_to_speak(void) {
// 0 = not in dialog
// 1 = starting dialog
// 2 = speaking
s32 set_mario_npc_dialog(s32 actionArg) {
s32 set_mario_npc_dialog(struct MarioState* m, s32 actionArg) {
s32 dialogState = 0;
// in dialog
if (gMarioState->action == ACT_READING_NPC_DIALOG) {
if (gMarioState->actionState < 8) {
if (m->action == ACT_READING_NPC_DIALOG) {
if (m->actionState < 8) {
dialogState = 1; // starting dialog
}
if (gMarioState->actionState == 8) {
if (m->actionState == 8) {
if (actionArg == 0) {
gMarioState->actionState++; // exit dialog
m->actionState++; // exit dialog
} else {
dialogState = 2;
}
}
} else if (actionArg != 0 && mario_ready_to_speak()) {
gMarioState->usedObj = gCurrentObject;
set_mario_action(gMarioState, ACT_READING_NPC_DIALOG, actionArg);
} else if (actionArg != 0 && mario_ready_to_speak(m)) {
m->usedObj = gCurrentObject;
set_mario_action(m, ACT_READING_NPC_DIALOG, actionArg);
dialogState = 1; // starting dialog
}

View file

@ -10,8 +10,8 @@ void print_displaying_credits_entry(void);
void bhv_end_peach_loop(void);
void bhv_end_toad_loop(void);
s32 geo_switch_peach_eyes(s32 run, struct GraphNode *node, UNUSED s32 a2);
s32 mario_ready_to_speak(void);
s32 set_mario_npc_dialog(s32 actionArg);
s32 mario_ready_to_speak(struct MarioState* m);
s32 set_mario_npc_dialog(struct MarioState* m, s32 actionArg);
s32 mario_execute_cutscene_action(struct MarioState *m);
#endif // MARIO_ACTIONS_CUTSCENE_H

View file

@ -124,7 +124,7 @@ static void toad_message_opaque(void) {
}
static void toad_message_talking(void) {
if (cur_obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId)
if (cur_obj_update_dialog_with_cutscene(&gMarioState[0], 3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId)
!= 0) {
gCurrentObject->oToadMessageRecentlyTalked = 1;
gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING;

View file

@ -519,42 +519,25 @@ s32 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist) {
* Returns either gMarioObject or gLuigiObject depending on what is closer
*/
struct MarioState* nearest_mario_state_to_object(struct Object *obj) {
f32 mx = gMarioState[0].marioObj->header.gfx.pos[0] - obj->oPosX;
f32 my = gMarioState[0].marioObj->header.gfx.pos[1] - obj->oPosY;
f32 mz = gMarioState[0].marioObj->header.gfx.pos[2] - obj->oPosZ;
mx *= mx;
my *= my;
mz *= mz;
struct MarioState* nearest = NULL;
f32 nearestDist = 0;
for (int i = 0; i < MAX_PLAYERS; i++) {
float dist = dist_between_objects(obj, gMarioState[i].marioObj);
if (nearest == NULL || dist < nearestDist) {
nearest = &gMarioState[i];
nearestDist = dist;
}
}
f32 lx = gMarioState[1].marioObj->header.gfx.pos[0] - obj->oPosX;
f32 ly = gMarioState[1].marioObj->header.gfx.pos[1] - obj->oPosY;
f32 lz = gMarioState[1].marioObj->header.gfx.pos[2] - obj->oPosZ;
lx *= lx;
ly *= ly;
lz *= lz;
return (mx + my + mz <= lx + ly + lz) ? &gMarioState[0] : &gMarioState[1];
return nearest;
}
/**
* Returns either gMarioObject or gLuigiObject depending on what is closer
*/
struct Object* nearest_player_to_object(struct Object *obj) {
f32 mx = gMarioObject->header.gfx.pos[0] - obj->oPosX;
f32 my = gMarioObject->header.gfx.pos[1] - obj->oPosY;
f32 mz = gMarioObject->header.gfx.pos[2] - obj->oPosZ;
mx *= mx;
my *= my;
mz *= mz;
f32 lx = gLuigiObject->header.gfx.pos[0] - obj->oPosX;
f32 ly = gLuigiObject->header.gfx.pos[1] - obj->oPosY;
f32 lz = gLuigiObject->header.gfx.pos[2] - obj->oPosZ;
lx *= lx;
ly *= ly;
lz *= lz;
return (mx + my + mz <= lx + ly + lz) ? gMarioObject : gLuigiObject;
struct MarioState* nearest = nearest_mario_state_to_object(obj);
return nearest->marioObj;
}
/**
@ -734,19 +717,21 @@ s8 current_mario_room_check(s16 room) {
/**
* Triggers dialog when Mario is facing an object and controls it while in the dialog.
*/
s16 trigger_obj_dialog_when_facing(s32 *inDialog, s16 dialogID, f32 dist, s32 actionArg) {
s16 trigger_obj_dialog_when_facing(struct MarioState* m, s32 *inDialog, s16 dialogID, f32 dist, s32 actionArg) {
s16 dialogueResponse;
int angleToPlayer = obj_angle_to_object(o, m->marioObj);
if ((is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, (s32) dist) == 1
&& obj_check_if_facing_toward_angle(o->oFaceAngleYaw, gMarioObject->header.gfx.angle[1] + 0x8000, 0x1000) == 1
&& obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x1000) == 1)
&& obj_check_if_facing_toward_angle(o->oFaceAngleYaw, m->marioObj->header.gfx.angle[1] + 0x8000, 0x1000) == 1
&& obj_check_if_facing_toward_angle(o->oMoveAngleYaw, angleToPlayer, 0x1000) == 1)
|| (*inDialog == 1)) {
*inDialog = 1;
if (set_mario_npc_dialog(actionArg) == 2) { //If Mario is speaking.
if (set_mario_npc_dialog(m, actionArg) == 2) { //If Mario is speaking.
dialogueResponse = cutscene_object_with_dialog(CUTSCENE_DIALOG, o, dialogID);
if (dialogueResponse != 0) {
set_mario_npc_dialog(0);
set_mario_npc_dialog(m, 0);
*inDialog = 0;
return dialogueResponse;
}

View file

@ -97,12 +97,12 @@ static s16 obj_get_pitch_from_vel(void) {
* If the player declines the race, then disable time stop and allow Mario to
* move again.
*/
static s32 obj_update_race_proposition_dialog(s16 dialogID) {
static s32 obj_update_race_proposition_dialog(struct MarioState* m, s16 dialogID) {
s32 dialogResponse =
cur_obj_update_dialog_with_cutscene(2, DIALOG_UNK2_FLAG_0 | DIALOG_UNK2_LEAVE_TIME_STOP_ENABLED, CUTSCENE_RACE_DIALOG, dialogID);
cur_obj_update_dialog_with_cutscene(m, 2, DIALOG_UNK2_FLAG_0 | DIALOG_UNK2_LEAVE_TIME_STOP_ENABLED, CUTSCENE_RACE_DIALOG, dialogID);
if (dialogResponse == 2) {
set_mario_npc_dialog(0);
set_mario_npc_dialog(m, 0);
disable_time_stop_including_mario();
}

View file

@ -2600,17 +2600,17 @@ void clear_time_stop_flags(s32 flags) {
gTimeStopState = gTimeStopState & (flags ^ 0xFFFFFFFF);
}
s32 cur_obj_can_mario_activate_textbox(f32 radius, f32 height, UNUSED s32 unused) {
s32 cur_obj_can_mario_activate_textbox(struct MarioState* m, f32 radius, f32 height, UNUSED s32 unused) {
f32 latDistToMario;
UNUSED s16 angleFromMario;
if (o->oDistanceToMario < 1500.0f) {
latDistToMario = lateral_dist_between_objects(o, gMarioObject);
angleFromMario = obj_angle_to_object(gMarioObject, o);
latDistToMario = lateral_dist_between_objects(o, m->marioObj);
angleFromMario = obj_angle_to_object(m->marioObj, o);
if (latDistToMario < radius && o->oPosY < gMarioObject->oPosY + 160.0f
&& gMarioObject->oPosY < o->oPosY + height && !(gMarioStates[0].action & ACT_FLAG_AIR)
&& mario_ready_to_speak()) {
if (latDistToMario < radius && o->oPosY < m->marioObj->oPosY + 160.0f
&& m->marioObj->oPosY < o->oPosY + height && !(m->action & ACT_FLAG_AIR)
&& mario_ready_to_speak(m)) {
return TRUE;
}
}
@ -2618,21 +2618,21 @@ s32 cur_obj_can_mario_activate_textbox(f32 radius, f32 height, UNUSED s32 unused
return FALSE;
}
s32 cur_obj_can_mario_activate_textbox_2(f32 radius, f32 height) {
s32 cur_obj_can_mario_activate_textbox_2(struct MarioState* m, f32 radius, f32 height) {
// The last argument here is unused. When this function is called directly the argument is always set to 0x7FFF.
return cur_obj_can_mario_activate_textbox(radius, height, 0x1000);
return cur_obj_can_mario_activate_textbox(m, radius, height, 0x1000);
}
static void cur_obj_end_dialog(s32 dialogFlags, s32 dialogResult) {
static void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult) {
o->oDialogResponse = dialogResult;
o->oDialogState++;
if (!(dialogFlags & DIALOG_UNK1_FLAG_4)) {
set_mario_npc_dialog(0);
set_mario_npc_dialog(m, 0);
}
}
s32 cur_obj_update_dialog(s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused) {
s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused) {
s32 dialogResponse = 0;
UNUSED s32 doneTurning = TRUE;
@ -2642,7 +2642,7 @@ s32 cur_obj_update_dialog(s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s
//! We enable time stop even if Mario is not ready to speak. This
// allows us to move during time stop as long as Mario never enters
// an action that can be interrupted with text.
if (gMarioState->health >= 0x100) {
if (m->health >= 0x100) {
gTimeStopState |= TIME_STOP_ENABLED;
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
o->oDialogState++;
@ -2652,7 +2652,7 @@ s32 cur_obj_update_dialog(s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s
case DIALOG_UNK1_ENABLE_TIME_STOP:
// Patched :(
// Wait for Mario to be ready to speak, and then enable time stop
if (mario_ready_to_speak() || gMarioState->action == ACT_READING_NPC_DIALOG) {
if (mario_ready_to_speak(m) || m->action == ACT_READING_NPC_DIALOG) {
//gTimeStopState |= TIME_STOP_ENABLED;
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
o->oDialogState++;
@ -2664,7 +2664,7 @@ s32 cur_obj_update_dialog(s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s
#endif
case DIALOG_UNK1_INTERRUPT_MARIO_ACTION:
if (set_mario_npc_dialog(actionArg) == 2) {
if (set_mario_npc_dialog(m, actionArg) == 2) {
o->oDialogState++;
}
break;
@ -2681,19 +2681,19 @@ s32 cur_obj_update_dialog(s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s
case DIALOG_UNK1_AWAIT_DIALOG:
if (dialogFlags & DIALOG_UNK1_FLAG_RESPONSE) {
if (gDialogResponse != 0) {
cur_obj_end_dialog(dialogFlags, gDialogResponse);
cur_obj_end_dialog(m, dialogFlags, gDialogResponse);
}
} else if (dialogFlags & DIALOG_UNK1_FLAG_DEFAULT) {
if (get_dialog_id() == -1) {
cur_obj_end_dialog(dialogFlags, 3);
cur_obj_end_dialog(m, dialogFlags, 3);
}
} else {
cur_obj_end_dialog(dialogFlags, 3);
cur_obj_end_dialog(m, dialogFlags, 3);
}
break;
case DIALOG_UNK1_DISABLE_TIME_STOP:
if (gMarioState->action != ACT_READING_NPC_DIALOG || (dialogFlags & DIALOG_UNK1_FLAG_4)) {
if (m->action != ACT_READING_NPC_DIALOG || (dialogFlags & DIALOG_UNK1_FLAG_4)) {
gTimeStopState &= ~TIME_STOP_ENABLED;
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
dialogResponse = o->oDialogResponse;
@ -2709,7 +2709,7 @@ s32 cur_obj_update_dialog(s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s
return dialogResponse;
}
s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID) {
s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID) {
s32 dialogResponse = 0;
s32 doneTurning = TRUE;
@ -2719,7 +2719,7 @@ s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cuts
//! We enable time stop even if Mario is not ready to speak. This
// allows us to move during time stop as long as Mario never enters
// an action that can be interrupted with text.
if (gMarioState->health >= 0x0100) {
if (m->health >= 0x0100) {
gTimeStopState |= TIME_STOP_ENABLED;
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
o->oDialogState++;
@ -2729,7 +2729,7 @@ s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cuts
#else
case DIALOG_UNK2_ENABLE_TIME_STOP:
// Wait for Mario to be ready to speak, and then enable time stop
if (mario_ready_to_speak() || gMarioState->action == ACT_READING_NPC_DIALOG) {
if (mario_ready_to_speak(m) || m->action == ACT_READING_NPC_DIALOG) {
//gTimeStopState |= TIME_STOP_ENABLED;
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
o->oDialogState++;
@ -2743,13 +2743,13 @@ s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cuts
case DIALOG_UNK2_TURN_AND_INTERRUPT_MARIO_ACTION:
if (dialogFlags & DIALOG_UNK2_FLAG_0) {
doneTurning = cur_obj_rotate_yaw_toward(obj_angle_to_object(o, gMarioObject), 0x800);
doneTurning = cur_obj_rotate_yaw_toward(obj_angle_to_object(o, m->marioObj), 0x800);
if (o->oDialogResponse >= 0x21) {
doneTurning = TRUE;
}
}
if (set_mario_npc_dialog(actionArg) == 2 && doneTurning) {
if (set_mario_npc_dialog(m, actionArg) == 2 && doneTurning) {
o->oDialogResponse = 0;
o->oDialogState++;
} else {
@ -2773,13 +2773,13 @@ s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cuts
if (dialogFlags & DIALOG_UNK2_LEAVE_TIME_STOP_ENABLED) {
dialogResponse = o->oDialogResponse;
o->oDialogState = DIALOG_UNK2_ENABLE_TIME_STOP;
} else if (gMarioState->action != ACT_READING_NPC_DIALOG) {
} else if (m->action != ACT_READING_NPC_DIALOG) {
gTimeStopState &= ~TIME_STOP_ENABLED;
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
dialogResponse = o->oDialogResponse;
o->oDialogState = DIALOG_UNK2_ENABLE_TIME_STOP;
} else {
set_mario_npc_dialog(0);
set_mario_npc_dialog(m, 0);
}
break;
}

View file

@ -276,10 +276,10 @@ void enable_time_stop(void);
void disable_time_stop(void);
void set_time_stop_flags(s32 flags);
void clear_time_stop_flags(s32 flags);
s32 cur_obj_can_mario_activate_textbox(f32 radius, f32 height, UNUSED s32 unused);
s32 cur_obj_can_mario_activate_textbox_2(f32 radius, f32 height);
s32 cur_obj_update_dialog(s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused);
s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID);
s32 cur_obj_can_mario_activate_textbox(struct MarioState* m, f32 radius, f32 height, UNUSED s32 unused);
s32 cur_obj_can_mario_activate_textbox_2(struct MarioState* m, f32 radius, f32 height);
s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused);
s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID);
s32 cur_obj_has_model(u16 modelID);
void cur_obj_align_gfx_with_floor(void);
s32 mario_is_within_rectangle(s16 minX, s16 maxX, s16 minZ, s16 maxZ);

View file

@ -63,25 +63,26 @@ void network_send_object(struct Object* o) {
struct Packet p;
packet_init(&p, PACKET_OBJECT, reliable);
packet_write(&p, &o->oSyncID, 4);
packet_write(&p, &so->onEventId, 2);
packet_write(&p, &so->onEventId, sizeof(u16));
packet_write(&p, &so->behavior, sizeof(void*));
packet_write(&p, &o->activeFlags, 2);
packet_write(&p, &o->activeFlags, sizeof(s16));
packet_write(&p, &o->header.gfx.node.flags, sizeof(s16));
if (so->fullObjectSync) {
packet_write(&p, o->rawData.asU32, 320);
packet_write(&p, o->rawData.asU32, sizeof(u32) * 80);
} else {
packet_write(&p, &o->oPosX, 28);
packet_write(&p, &o->oAction, 4);
packet_write(&p, &o->oSubAction, 4);
packet_write(&p, &o->oInteractStatus, 4);
packet_write(&p, &o->oHeldState, 4);
packet_write(&p, &o->oMoveAngleYaw, 4);
packet_write(&p, &o->oTimer, 4);
packet_write(&p, &o->oPosX, sizeof(u32) * 7);
packet_write(&p, &o->oAction, sizeof(u32));
packet_write(&p, &o->oSubAction, sizeof(u32));
packet_write(&p, &o->oInteractStatus, sizeof(u32));
packet_write(&p, &o->oHeldState, sizeof(u32));
packet_write(&p, &o->oMoveAngleYaw, sizeof(u32));
packet_write(&p, &o->oTimer, sizeof(u32));
packet_write(&p, &so->extraFieldCount, 1);
packet_write(&p, &so->extraFieldCount, sizeof(u8));
for (int i = 0; i < so->extraFieldCount; i++) {
assert(so->extraFields[i] != NULL);
packet_write(&p, so->extraFields[i], 4);
packet_write(&p, so->extraFields[i], sizeof(u32));
}
}
@ -101,7 +102,7 @@ void network_send_object(struct Object* o) {
void network_receive_object(struct Packet* p) {
// get sync ID
u32 syncId;
packet_read(p, &syncId, 4);
packet_read(p, &syncId, sizeof(u32));
assert(syncId < MAX_SYNC_OBJECTS);
// retrieve SyncObject
@ -119,7 +120,7 @@ void network_receive_object(struct Packet* p) {
// make sure this is the newest event possible
volatile u16 eventId = 0;
packet_read(p, &eventId, 2);
packet_read(p, &eventId, sizeof(u16));
if (so->onEventId > eventId && (u16)abs(eventId - so->onEventId) < USHRT_MAX / 2) { return; }
so->onEventId = eventId;
@ -134,7 +135,7 @@ void network_receive_object(struct Packet* p) {
// sync only death
if (so->maxSyncDistance == SYNC_DISTANCE_ONLY_DEATH) {
s16 activeFlags;
packet_read(p, &activeFlags, 2);
packet_read(p, &activeFlags, sizeof(u16));
if (activeFlags == ACTIVE_FLAG_DEACTIVATED) {
so->o->oSyncDeath = 1;
forget_sync_object(so);
@ -142,28 +143,33 @@ void network_receive_object(struct Packet* p) {
return;
}
if (gMarioStates[0].heldObj == o) {
return;
}
// write object flags
packet_read(p, &o->activeFlags, 2);
packet_read(p, &o->activeFlags, sizeof(u16));
packet_read(p, &o->header.gfx.node.flags, sizeof(s16));
if (so->fullObjectSync) {
packet_read(p, o->rawData.asU32, 320);
packet_read(p, o->rawData.asU32, sizeof(u32) * 80);
} else {
packet_read(p, &o->oPosX, 28);
packet_read(p, &o->oAction, 4);
packet_read(p, &o->oSubAction, 4);
packet_read(p, &o->oInteractStatus, 4);
packet_read(p, &o->oHeldState, 4);
packet_read(p, &o->oMoveAngleYaw, 4);
packet_read(p, &o->oTimer, 4);
packet_read(p, &o->oPosX, sizeof(u32) * 7);
packet_read(p, &o->oAction, sizeof(u32));
packet_read(p, &o->oSubAction, sizeof(u32));
packet_read(p, &o->oInteractStatus, sizeof(u32));
packet_read(p, &o->oHeldState, sizeof(u32));
packet_read(p, &o->oMoveAngleYaw, sizeof(u32));
packet_read(p, &o->oTimer, sizeof(u32));
}
// write extra fields
u8 extraFields = 0;
packet_read(p, &extraFields, 1);
packet_read(p, &extraFields, sizeof(u8));
assert(extraFields == so->extraFieldCount);
for (int i = 0; i < extraFields; i++) {
assert(so->extraFields[i] != NULL);
packet_read(p, so->extraFields[i], 4);
packet_read(p, so->extraFields[i], sizeof(u32));
}
// deactivated
@ -232,4 +238,4 @@ void network_update_objects(void) {
network_send_object(syncObjects[i].o);
}
}
}

View file

@ -8,15 +8,19 @@ void network_send_player(void) {
u32 heldSyncID = (gMarioStates[0].heldObj != NULL)
? gMarioStates[0].heldObj->oSyncID
: NULL;
u32 heldBySyncID = (gMarioStates[0].heldByObj != NULL)
? gMarioStates[0].heldByObj->oSyncID
: NULL;
struct Packet p;
packet_init(&p, PACKET_PLAYER, false);
packet_write(&p, &gMarioStates[0], 96);
packet_write(&p, &gMarioStates[0], sizeof(u32) * 24);
packet_write(&p, gMarioStates[0].controller, 20);
packet_write(&p, gMarioStates[0].marioObj->rawData.asU32, 320);
packet_write(&p, &gMarioStates[0].health, 2);
packet_write(&p, &heldSyncID, 4);
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, &heldSyncID, sizeof(u32));
packet_write(&p, &heldBySyncID, sizeof(u32));
network_send(&p);
}
@ -24,21 +28,31 @@ void network_receive_player(struct Packet* p) {
if (gMarioStates[1].marioObj == NULL) { return; }
int oldActionState = gMarioStates[1].actionState;
u32 heldSyncID = NULL;
u32 heldBySyncID = NULL;
packet_read(p, &gMarioStates[1], 96);
packet_read(p, &gMarioStates[1], sizeof(u32) * 24);
packet_read(p, gMarioStates[1].controller, 20);
packet_read(p, &gMarioStates[1].marioObj->rawData.asU32, 320);
packet_read(p, &gMarioStates[1].health, 2);
packet_read(p, &heldSyncID, 4);
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, &heldSyncID, sizeof(u32));
packet_read(p, &heldBySyncID, sizeof(u32));
if (heldSyncID != NULL) {
assert(syncObjects[heldSyncID].o != NULL);
if (heldSyncID != NULL && syncObjects[heldSyncID].o != NULL) {
// TODO: do we have to move graphics nodes around to make this visible?
gMarioStates[1].heldObj = syncObjects[heldSyncID].o;
gMarioStates[1].heldObj->heldByPlayerIndex = 1;
} else {
gMarioStates[1].heldObj = NULL;
}
if (heldBySyncID != NULL && syncObjects[heldBySyncID].o != NULL) {
// TODO: do we have to move graphics nodes around to make this visible?
gMarioStates[1].heldByObj = syncObjects[heldBySyncID].o;
} else {
gMarioStates[1].heldByObj = NULL;
}
// restore action state, needed for jump kicking
gMarioStates[1].actionState = oldActionState;
}