diff --git a/data/behavior_data.c b/data/behavior_data.c index 7ddcc9afa..6b7b03055 100644 --- a/data/behavior_data.c +++ b/data/behavior_data.c @@ -839,7 +839,6 @@ const BehaviorScript bhvWfRotatingWoodenPlatform[] = { LOAD_COLLISION_DATA(wf_seg7_collision_clocklike_rotation), BEGIN_LOOP(), CALL_NATIVE(bhv_wf_rotating_wooden_platform_loop), - CALL_NATIVE(load_object_collision_model), END_LOOP(), }; @@ -1749,7 +1748,6 @@ const BehaviorScript bhvWfSlidingTowerPlatform[] = { LOAD_COLLISION_DATA(wf_seg7_collision_platform), BEGIN_LOOP(), CALL_NATIVE(bhv_wf_sliding_tower_platform_loop), - CALL_NATIVE(load_object_collision_model), END_LOOP(), }; @@ -1771,7 +1769,6 @@ const BehaviorScript bhvWfSolidTowerPlatform[] = { LOAD_COLLISION_DATA(wf_seg7_collision_platform), BEGIN_LOOP(), CALL_NATIVE(bhv_wf_solid_tower_platform_loop), - CALL_NATIVE(load_object_collision_model), END_LOOP(), }; @@ -2699,7 +2696,6 @@ const BehaviorScript bhvLllBowserPuzzlePiece[] = { SET_FLOAT(oCollisionDistance, 3000), BEGIN_LOOP(), CALL_NATIVE(bhv_lll_bowser_puzzle_piece_loop), - CALL_NATIVE(load_object_collision_model), END_LOOP(), }; @@ -4639,7 +4635,6 @@ const BehaviorScript bhvSmallBomp[] = { CALL_NATIVE(bhv_small_bomp_init), BEGIN_LOOP(), CALL_NATIVE(bhv_small_bomp_loop), - CALL_NATIVE(load_object_collision_model), END_LOOP(), }; @@ -4651,7 +4646,6 @@ const BehaviorScript bhvLargeBomp[] = { CALL_NATIVE(bhv_large_bomp_init), BEGIN_LOOP(), CALL_NATIVE(bhv_large_bomp_loop), - CALL_NATIVE(load_object_collision_model), END_LOOP(), }; @@ -4663,7 +4657,6 @@ const BehaviorScript bhvWfSlidingPlatform[] = { CALL_NATIVE(bhv_wf_sliding_platform_init), BEGIN_LOOP(), CALL_NATIVE(bhv_wf_sliding_platform_loop), - CALL_NATIVE(load_object_collision_model), END_LOOP(), }; @@ -6567,7 +6560,6 @@ const BehaviorScript bhvDDDPole[] = { SET_FLOAT(oDDDPoleVel, 10), BEGIN_LOOP(), CALL_NATIVE(bhv_ddd_pole_update), - CALL_NATIVE(bhv_pole_base_loop), END_LOOP(), }; diff --git a/include/types.h b/include/types.h index d06a0503b..85151adf8 100644 --- a/include/types.h +++ b/include/types.h @@ -230,6 +230,7 @@ struct Object /*?????*/ enum AreaTimerType areaTimerType; /*?????*/ u32 areaTimer; /*?????*/ u32 areaTimerDuration; + /*?????*/ void (*areaTimerRunOnceCallback)(void); /*?????*/ u8 globalPlayerIndex; }; diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index bf63c7359..dd245d14a 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -955,7 +955,7 @@ void cur_obj_update(void) { if (gCurrentObject->areaTimerType != AREA_TIMER_TYPE_NONE) { // make sure the area is valid if (gNetworkPlayerLocal == NULL || !gNetworkPlayerLocal->currAreaSyncValid) { - return; + goto cur_obj_update_end; } // catch up the timer in total loop increments @@ -984,7 +984,7 @@ void cur_obj_update(void) { // cancel object update if it's running faster than the timer if (gCurrentObject->areaTimer > gNetworkAreaTimer) { - return; + goto cur_obj_update_end; } } @@ -1098,6 +1098,14 @@ cur_obj_update_begin:; goto cur_obj_update_begin; } } + + // call the network area timer's run-once callback +cur_obj_update_end:; + if (gCurrentObject->areaTimerType != AREA_TIMER_TYPE_NONE) { + if (gCurrentObject->areaTimerRunOnceCallback != NULL) { + gCurrentObject->areaTimerRunOnceCallback(); + } + } } u16 position_based_random_u16(void) { diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index 947f1ab45..e575c4188 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -762,11 +762,6 @@ void load_object_surfaces(s16** data, s16* vertexData) { * Transform an object's vertices, reload them, and render the object. */ void load_object_collision_model(void) { - if (gCurrentObject->areaTimerType != AREA_TIMER_TYPE_NONE) { - // only load collision model on last frame - if (!cur_obj_is_last_nat_update_per_frame()) { return; } - } - UNUSED s32 unused; s16 vertexData[600]; diff --git a/src/game/behaviors/bomp.inc.c b/src/game/behaviors/bomp.inc.c index 3b725a0ae..e5783bced 100644 --- a/src/game/behaviors/bomp.inc.c +++ b/src/game/behaviors/bomp.inc.c @@ -7,6 +7,7 @@ void bhv_small_bomp_init(void) { o->areaTimerType = AREA_TIMER_TYPE_LOOP; o->areaTimer = 0; o->areaTimerDuration = 168; + o->areaTimerRunOnceCallback = load_object_collision_model; } void bhv_small_bomp_loop(void) { @@ -66,6 +67,7 @@ void bhv_large_bomp_init(void) { o->areaTimerType = AREA_TIMER_TYPE_LOOP; o->areaTimer = 0; o->areaTimerDuration = 168; + o->areaTimerRunOnceCallback = load_object_collision_model; } void bhv_large_bomp_loop(void) { diff --git a/src/game/behaviors/bowser_puzzle_piece.inc.c b/src/game/behaviors/bowser_puzzle_piece.inc.c index f151435ae..f4b00352a 100644 --- a/src/game/behaviors/bowser_puzzle_piece.inc.c +++ b/src/game/behaviors/bowser_puzzle_piece.inc.c @@ -98,6 +98,7 @@ void bhv_lll_bowser_puzzle_spawn_piece(s16 model, const BehaviorScript *behavior puzzlePiece->areaTimerType = AREA_TIMER_TYPE_LOOP; puzzlePiece->areaTimer = 0; puzzlePiece->areaTimerDuration = 650; + puzzlePiece->areaTimerRunOnceCallback = load_object_collision_model; } /** diff --git a/src/game/behaviors/checkerboard_platform.inc.c b/src/game/behaviors/checkerboard_platform.inc.c index b45a35c8f..aa41d0dda 100644 --- a/src/game/behaviors/checkerboard_platform.inc.c +++ b/src/game/behaviors/checkerboard_platform.inc.c @@ -48,19 +48,22 @@ void checkerboard_plat_act_rotate(s32 a0, s16 a1) { o->oCheckerBoardPlatformUnkF8 = a0; } +static void bhv_checkerboard_platform_run_once(void) { + if (o->oDistanceToMario < 1000.0f) { + cur_obj_play_sound_1(SOUND_ENV_ELEVATOR4); + } + load_object_collision_model(); +} + void bhv_checkerboard_platform_init(void) { o->oCheckerBoardPlatformUnkFC = o->parentObj->oBehParams2ndByte; o->areaTimerType = AREA_TIMER_TYPE_LOOP; o->areaTimer = 0; o->areaTimerDuration = 132 + o->oCheckerBoardPlatformUnkFC * 2; + o->areaTimerRunOnceCallback = bhv_checkerboard_platform_run_once; } void bhv_checkerboard_platform_loop(void) { - bool lastNATUpdate = cur_obj_is_last_nat_update_per_frame(); - if (o->oDistanceToMario < 1000.0f && lastNATUpdate) { - cur_obj_play_sound_1(SOUND_ENV_ELEVATOR4); - } - f32 sp24 = o->oCheckerBoardPlatformUnk1AC; o->oCheckerBoardPlatformUnkF8 = 0; switch (o->oAction) { @@ -97,8 +100,4 @@ void bhv_checkerboard_platform_loop(void) { } else { cur_obj_move_using_fvel_and_gravity(); } - - if (lastNATUpdate) { - load_object_collision_model(); - } } diff --git a/src/game/behaviors/ddd_pole.inc.c b/src/game/behaviors/ddd_pole.inc.c index 48339e1fd..595e2e9e5 100644 --- a/src/game/behaviors/ddd_pole.inc.c +++ b/src/game/behaviors/ddd_pole.inc.c @@ -10,6 +10,7 @@ void bhv_ddd_pole_init(void) { o->areaTimerType = AREA_TIMER_TYPE_LOOP; o->areaTimer = 0; o->areaTimerDuration = (((u16)o->oDDDPoleMaxOffset / 10) + 20) * 2; + o->areaTimerRunOnceCallback = bhv_pole_base_loop; } void bhv_ddd_pole_update(void) { diff --git a/src/game/behaviors/koopa.inc.c b/src/game/behaviors/koopa.inc.c index 20b61c535..baf02d1e2 100644 --- a/src/game/behaviors/koopa.inc.c +++ b/src/game/behaviors/koopa.inc.c @@ -88,6 +88,10 @@ void bhv_koopa_the_quick_override_ownership(u8* shouldOverride, u8* shouldOwn) { *shouldOwn = (get_network_player_smallest_global() == gNetworkPlayerLocal); } +static void bhv_koopa_the_quick_run_once(void) { + cur_obj_push_mario_away_from_cylinder(140.0f, 300.0f); +} + /** * Initialization function. */ @@ -140,6 +144,7 @@ void bhv_koopa_init(void) { o->areaTimerType = AREA_TIMER_TYPE_MAXIMUM; o->areaTimer = 0; o->areaTimerDuration = 60; + o->areaTimerRunOnceCallback = bhv_koopa_the_quick_run_once; } else { // normal koopa network_init_object(o, 4000.0f); @@ -902,9 +907,6 @@ static void koopa_the_quick_update(void) { } } - if (cur_obj_is_last_nat_update_per_frame()) { - cur_obj_push_mario_away_from_cylinder(140.0f, 300.0f); - } cur_obj_move_standard(-78); } diff --git a/src/game/behaviors/racing_penguin.inc.c b/src/game/behaviors/racing_penguin.inc.c index 2efb95da1..9898bde00 100644 --- a/src/game/behaviors/racing_penguin.inc.c +++ b/src/game/behaviors/racing_penguin.inc.c @@ -29,6 +29,13 @@ void bhv_racing_penguin_the_quick_override_ownership(u8* shouldOverride, u8* sho *shouldOwn = (get_network_player_smallest_global() == gNetworkPlayerLocal); } +void bhv_racing_penguin_run_once(void) { + cur_obj_align_gfx_with_floor(); + cur_obj_push_mario_away_from_cylinder( + sRacingPenguinData[o->oBehParams2ndByte].radius, + sRacingPenguinData[o->oBehParams2ndByte].height); +} + void bhv_racing_penguin_init(void) { if (gMarioStates[0].numStars == 120) { cur_obj_scale(8.0f); @@ -70,6 +77,7 @@ void bhv_racing_penguin_init(void) { o->areaTimerType = AREA_TIMER_TYPE_MAXIMUM; o->areaTimer = 0; o->areaTimerDuration = 60; + o->areaTimerRunOnceCallback = bhv_racing_penguin_run_once; } static void racing_penguin_act_wait_for_mario(void) { @@ -277,12 +285,6 @@ void bhv_racing_penguin_update(void) { } cur_obj_move_standard(78); - - if (cur_obj_is_last_nat_update_per_frame()) { - cur_obj_align_gfx_with_floor(); - cur_obj_push_mario_away_from_cylinder(sRacingPenguinData[o->oBehParams2ndByte].radius, - sRacingPenguinData[o->oBehParams2ndByte].height); - } } void bhv_penguin_race_finish_line_update(void) { diff --git a/src/game/behaviors/rotating_platform.inc.c b/src/game/behaviors/rotating_platform.inc.c index 3bf4b5f91..921e55ad1 100644 --- a/src/game/behaviors/rotating_platform.inc.c +++ b/src/game/behaviors/rotating_platform.inc.c @@ -8,14 +8,21 @@ struct WFRotatingPlatformData sWFRotatingPlatformData[] = { { 0, 150, wdw_seg7_collision_070186B4, 1000 } }; +static void bhv_wf_rotating_wooden_platform_run_once(void) { + if (o->oAction != 0) { + cur_obj_play_sound_1(SOUND_ENV_ELEVATOR2); + } + load_object_collision_model(); +} + void bhv_wf_rotating_wooden_platform_init(void) { o->areaTimerType = AREA_TIMER_TYPE_LOOP; o->areaTimer = 0; o->areaTimerDuration = 380; + o->areaTimerRunOnceCallback = bhv_wf_rotating_wooden_platform_run_once; } void bhv_wf_rotating_wooden_platform_loop(void) { - bool lastNATUpdate = cur_obj_is_last_nat_update_per_frame(); if (o->oAction == 0) { o->oAngleVelYaw = 0; if (o->oTimer > 60) { @@ -26,9 +33,6 @@ void bhv_wf_rotating_wooden_platform_loop(void) { if (o->oTimer > 126) { o->oAction = 0; } - if (lastNATUpdate) { - cur_obj_play_sound_1(SOUND_ENV_ELEVATOR2); - } } cur_obj_rotate_face_angle_using_vel(); } diff --git a/src/game/behaviors/sliding_platform.inc.c b/src/game/behaviors/sliding_platform.inc.c index e8f126b36..c9a9d6e7f 100644 --- a/src/game/behaviors/sliding_platform.inc.c +++ b/src/game/behaviors/sliding_platform.inc.c @@ -24,6 +24,7 @@ void bhv_wf_sliding_platform_init(void) { o->areaTimerType = AREA_TIMER_TYPE_LOOP; o->areaTimer = 0; o->areaTimerDuration = 152; + o->areaTimerRunOnceCallback = load_object_collision_model; } void bhv_wf_sliding_platform_loop(void) { diff --git a/src/game/behaviors/tower_platform.inc.c b/src/game/behaviors/tower_platform.inc.c index 7c3d25e42..c9f5a37a3 100644 --- a/src/game/behaviors/tower_platform.inc.c +++ b/src/game/behaviors/tower_platform.inc.c @@ -94,12 +94,15 @@ void spawn_and_init_wf_platforms(s16 a, const BehaviorScript *bhv) { platform->oPlatformUnk10C = o->oPlatformSpawnerUnk108; o->oPlatformSpawnerUnkF4++; - u32 loopTime = 1 + (platform->oPlatformUnk110 / platform->oPlatformUnk10C); - loopTime *= 2; - loopTime += 1; - platform->areaTimerType = AREA_TIMER_TYPE_LOOP; - platform->areaTimer = 0; - platform->areaTimerDuration = loopTime; + if (bhv == bhvWfSolidTowerPlatform || bhv == bhvWfSlidingTowerPlatform) { + u32 loopTime = 1 + (platform->oPlatformUnk110 / platform->oPlatformUnk10C); + loopTime *= 2; + loopTime += 1; + platform->areaTimerType = AREA_TIMER_TYPE_LOOP; + platform->areaTimer = 0; + platform->areaTimerDuration = loopTime; + platform->areaTimerRunOnceCallback = load_object_collision_model; + } } void spawn_wf_platform_group(void) { diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index 2b7b9600e..15bc24231 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -31,6 +31,7 @@ #include "save_file.h" #include "spawn_object.h" #include "spawn_sound.h" +#include "engine/surface_load.h" #include "pc/network/network.h" #include "pc/network/reservation_area.h" #include "game/rng_position.h" diff --git a/src/game/obj_behaviors_2.c b/src/game/obj_behaviors_2.c index bed2e7a8f..4f44f8bc1 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -44,6 +44,7 @@ #include "save_file.h" #include "seq_ids.h" #include "spawn_sound.h" +#include "engine/surface_load.h" #include "pc/network/network.h" #include "pc/network/reservation_area.h" diff --git a/src/game/spawn_object.c b/src/game/spawn_object.c index 3888792d7..afaedf23e 100644 --- a/src/game/spawn_object.c +++ b/src/game/spawn_object.c @@ -309,6 +309,7 @@ struct Object *allocate_object(struct ObjectNode *objList) { obj->areaTimerType = AREA_TIMER_TYPE_NONE; obj->areaTimer = 0; obj->areaTimerDuration = 0; + obj->areaTimerRunOnceCallback = NULL; return obj; }