From fecba91c5ed2304657c284ddd44beb28c3f31c7d Mon Sep 17 00:00:00 2001 From: MysterD Date: Tue, 10 Aug 2021 18:21:10 -0700 Subject: [PATCH] Rewrite the core of network area timer (yet again) --- data/behavior_data.c | 1 + include/types.h | 1 + src/engine/behavior_script.c | 108 +++++------------- src/engine/behavior_script.h | 2 +- src/engine/math_util.c | 4 +- src/engine/surface_load.c | 5 + src/game/behavior_actions.h | 1 + src/game/behaviors/bomp.inc.c | 16 +-- src/game/behaviors/bowser_puzzle_piece.inc.c | 8 +- .../behaviors/checkerboard_platform.inc.c | 62 +++++----- src/game/behaviors/ddd_pole.inc.c | 9 +- src/game/behaviors/rotating_platform.inc.c | 19 +-- src/game/behaviors/sliding_platform.inc.c | 8 +- src/game/behaviors/tower_platform.inc.c | 15 ++- src/game/obj_behaviors.c | 2 + src/game/spawn_object.c | 7 +- src/pc/network/network.c | 40 +++++-- 17 files changed, 147 insertions(+), 161 deletions(-) diff --git a/data/behavior_data.c b/data/behavior_data.c index e1ad6ed93..0cb073972 100644 --- a/data/behavior_data.c +++ b/data/behavior_data.c @@ -832,6 +832,7 @@ const BehaviorScript bhvWfRotatingWoodenPlatform[] = { BEGIN(OBJ_LIST_SURFACE), ID(id_bhvWfRotatingWoodenPlatform), OR_INT(oFlags, OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE), + CALL_NATIVE(bhv_wf_rotating_wooden_platform_init), LOAD_COLLISION_DATA(wf_seg7_collision_clocklike_rotation), BEGIN_LOOP(), CALL_NATIVE(bhv_wf_rotating_wooden_platform_loop), diff --git a/include/types.h b/include/types.h index 92aeabf80..8281c7ae2 100644 --- a/include/types.h +++ b/include/types.h @@ -222,6 +222,7 @@ struct Object /*0x25C*/ void *respawnInfo; /*?????*/ u8 createdThroughNetwork; /*?????*/ u32 areaTimer; + /*?????*/ u32 areaTimerLoopLength; /*?????*/ u8 globalPlayerIndex; }; diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index 50613400d..aa6cb80c0 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -951,6 +951,29 @@ static BhvCommandProc BehaviorCmdTable[] = { // Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects. void cur_obj_update(void) { + // handle network area timer + if (gCurrentObject->areaTimerLoopLength > 0) { + // make sure the area is valid + if (gNetworkPlayerLocal == NULL || !gNetworkPlayerLocal->currAreaSyncValid) { + return; + } + + // catch up the timer in total loop increments + u32 difference = (gNetworkAreaTimer - gCurrentObject->areaTimer); + if (difference >= gCurrentObject->areaTimerLoopLength) { + u32 catchup = difference / gCurrentObject->areaTimerLoopLength; + catchup *= gCurrentObject->areaTimerLoopLength; + gCurrentObject->areaTimer += catchup; + } + + // cancel object update if it's running faster than the timer + if (gCurrentObject->areaTimer >= gNetworkAreaTimer) { + return; + } + } + +cur_obj_update_begin:; + UNUSED u32 unused; s16 objFlags = gCurrentObject->oFlags; @@ -1051,70 +1074,13 @@ void cur_obj_update(void) { } } } -} -// Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects. -void cur_obj_fake_update(void) { - UNUSED u32 unused; - - s16 objFlags = gCurrentObject->oFlags; - - // Increment the object's timer. - if (gCurrentObject->oTimer < 0x3FFFFFFF) { - gCurrentObject->oTimer++; - } - - // If the object's action has changed, reset the action timer. - if (gCurrentObject->oAction != gCurrentObject->oPrevAction) { - (void) (gCurrentObject->oTimer = 0, gCurrentObject->oSubAction = 0, - gCurrentObject->oPrevAction = gCurrentObject->oAction); - } - - // Execute various code based on object flags. - objFlags = (s16) gCurrentObject->oFlags; - - if (objFlags & OBJ_FLAG_SET_FACE_ANGLE_TO_MOVE_ANGLE) { - obj_set_face_angle_to_move_angle(gCurrentObject); - } - - if (objFlags & OBJ_FLAG_SET_FACE_YAW_TO_MOVE_YAW) { - gCurrentObject->oFaceAngleYaw = gCurrentObject->oMoveAngleYaw; - } - - if (objFlags & OBJ_FLAG_MOVE_XZ_USING_FVEL) { - cur_obj_move_xz_using_fvel_and_yaw(); - } - - if (objFlags & OBJ_FLAG_MOVE_Y_WITH_TERMINAL_VEL) { - cur_obj_move_y_with_terminal_vel(); - } - - if (objFlags & OBJ_FLAG_TRANSFORM_RELATIVE_TO_PARENT) { - obj_build_transform_relative_to_parent(gCurrentObject); - } - - if (objFlags & OBJ_FLAG_SET_THROW_MATRIX_FROM_TRANSFORM) { - obj_set_throw_matrix_from_transform(gCurrentObject); - } - - if (objFlags & OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE) { - obj_update_gfx_pos_and_angle(gCurrentObject); - } - - // Calculate the distance from the object to Mario. - if (objFlags & OBJ_FLAG_COMPUTE_DIST_TO_MARIO) { - gCurrentObject->oDistanceToMario = dist_between_objects(gCurrentObject, gMarioObject); - } - - // Calculate the angle from the object to Mario. - if (objFlags & OBJ_FLAG_COMPUTE_ANGLE_TO_MARIO) { - gCurrentObject->oAngleToMario = obj_angle_to_object(gCurrentObject, gMarioObject); - } - - // If the object's action has changed, reset the action timer. - if (gCurrentObject->oAction != gCurrentObject->oPrevAction) { - (void)(gCurrentObject->oTimer = 0, gCurrentObject->oSubAction = 0, - gCurrentObject->oPrevAction = gCurrentObject->oAction); + // update network area timer + if (gCurrentObject->areaTimerLoopLength > 0) { + gCurrentObject->areaTimer++; + if (gCurrentObject->areaTimer < gNetworkAreaTimer) { + goto cur_obj_update_begin; + } } } @@ -1130,18 +1096,6 @@ f32 position_based_random_float_position(void) { return rnd / (double)0x10000; } -void cur_obj_area_timer_loop(u32 loopLength, void (*func)(void)) { - if ((gNetworkAreaTimer - gCurrentObject->areaTimer) >= loopLength) { - u32 catchup = (gNetworkAreaTimer - gCurrentObject->areaTimer) / loopLength; - catchup *= loopLength; - gCurrentObject->areaTimer += catchup; - } - - while (gCurrentObject->areaTimer < gNetworkAreaTimer) { - (*func)(); - gCurrentObject->areaTimer++; - if (gCurrentObject->areaTimer < gNetworkAreaTimer) { - cur_obj_fake_update(); - } - } +u8 cur_obj_is_last_nat_update_per_frame(void) { + return (gCurrentObject->areaTimer == (gNetworkAreaTimer - 1)); } diff --git a/src/engine/behavior_script.h b/src/engine/behavior_script.h index 04d928a33..e7222aa20 100644 --- a/src/engine/behavior_script.h +++ b/src/engine/behavior_script.h @@ -30,6 +30,6 @@ void cur_obj_fake_update(void); u16 position_based_random_u16(void); f32 position_based_random_float_position(void); -void cur_obj_area_timer_loop(u32 loopLength, void (*func)(void)); +u8 cur_obj_is_last_nat_update_per_frame(void); #endif // BEHAVIOR_SCRIPT_H diff --git a/src/engine/math_util.c b/src/engine/math_util.c index 0ce743b67..c398243b3 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -735,7 +735,9 @@ static u16 atan2_lookup(f32 y, f32 x) { if (x == 0) { ret = gArctanTable[0]; } else { - ret = gArctanTable[(s32)(y / x * 1024 + 0.5f)]; + s32 index = (s32)(y / x * 1024 + 0.5f); + if (index >= 0x401) { index = 0; } + ret = gArctanTable[index]; } return ret; } diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index e575c4188..798065124 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -762,6 +762,11 @@ 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->areaTimerLoopLength > 0) { + // 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/behavior_actions.h b/src/game/behavior_actions.h index f118d5f97..26d77ea97 100644 --- a/src/game/behavior_actions.h +++ b/src/game/behavior_actions.h @@ -59,6 +59,7 @@ void bhv_rotating_platform_loop(void); void bhv_wf_breakable_wall_loop(void); void bhv_kickable_board_loop(void); void bhv_tower_door_loop(void); +void bhv_wf_rotating_wooden_platform_init(void); void bhv_wf_rotating_wooden_platform_loop(void); void bhv_koopa_shell_underwater_loop(void); void bhv_fading_warp_loop(void); diff --git a/src/game/behaviors/bomp.inc.c b/src/game/behaviors/bomp.inc.c index 569b71f90..33b60c63e 100644 --- a/src/game/behaviors/bomp.inc.c +++ b/src/game/behaviors/bomp.inc.c @@ -4,9 +4,11 @@ void bhv_small_bomp_init(void) { o->oFaceAngleYaw -= 0x4000; o->oSmallBompInitX = o->oPosX; o->oTimer = position_based_random_float_position() * 100.0f; + o->areaTimer = 0; + o->areaTimerLoopLength = 168; } -static void bhv_small_bomp_loop_inner(void) { +void bhv_small_bomp_loop(void) { switch (o->oAction) { case BOMP_ACT_WAIT: if (o->oTimer >= 101) { @@ -57,16 +59,14 @@ static void bhv_small_bomp_loop_inner(void) { } } -void bhv_small_bomp_loop(void) { - cur_obj_area_timer_loop(168, bhv_small_bomp_loop_inner); -} - void bhv_large_bomp_init(void) { o->oMoveAngleYaw += 0x4000; o->oTimer = position_based_random_float_position() * 100.0f; + o->areaTimer = 0; + o->areaTimerLoopLength = 168; } -void bhv_large_bomp_loop_inner(void) { +void bhv_large_bomp_loop(void) { switch (o->oAction) { case BOMP_ACT_WAIT: if (o->oTimer >= 101) { @@ -116,7 +116,3 @@ void bhv_large_bomp_loop_inner(void) { break; } } - -void bhv_large_bomp_loop(void) { - cur_obj_area_timer_loop(168, bhv_large_bomp_loop_inner); -} diff --git a/src/game/behaviors/bowser_puzzle_piece.inc.c b/src/game/behaviors/bowser_puzzle_piece.inc.c index dc800a5b5..b3e8969c5 100644 --- a/src/game/behaviors/bowser_puzzle_piece.inc.c +++ b/src/game/behaviors/bowser_puzzle_piece.inc.c @@ -95,6 +95,8 @@ void bhv_lll_bowser_puzzle_spawn_piece(s16 model, const BehaviorScript *behavior puzzlePiece->oBowserPuzzlePieceActionList = actionList; puzzlePiece->oBowserPuzzlePieceNextAction = actionList; puzzlePiece->oTimer = 0; + puzzlePiece->areaTimer = 0; + puzzlePiece->areaTimerLoopLength = 650; } /** @@ -257,7 +259,7 @@ void (*sBowserPuzzlePieceActions[])(void) = { bhv_lll_bowser_puzzle_piece_move_down }; -void bhv_lll_bowser_puzzle_piece_loop_inner(void) { +void bhv_lll_bowser_puzzle_piece_loop(void) { bhv_lll_bowser_puzzle_piece_update(); cur_obj_call_action_function(sBowserPuzzlePieceActions); @@ -266,7 +268,3 @@ void bhv_lll_bowser_puzzle_piece_loop_inner(void) { o->oPosY = o->oBowserPuzzlePieceOffsetY + o->oHomeY; o->oPosZ = o->oBowserPuzzlePieceOffsetZ + o->oHomeZ; } - -void bhv_lll_bowser_puzzle_piece_loop(void) { - cur_obj_area_timer_loop(650, bhv_lll_bowser_puzzle_piece_loop_inner); -} diff --git a/src/game/behaviors/checkerboard_platform.inc.c b/src/game/behaviors/checkerboard_platform.inc.c index b9ae00c58..4d317f2ab 100644 --- a/src/game/behaviors/checkerboard_platform.inc.c +++ b/src/game/behaviors/checkerboard_platform.inc.c @@ -50,30 +50,37 @@ void checkerboard_plat_act_rotate(s32 a0, s16 a1) { void bhv_checkerboard_platform_init(void) { o->oCheckerBoardPlatformUnkFC = o->parentObj->oBehParams2ndByte; + o->areaTimer = 0; + o->areaTimerLoopLength = 132 + o->oCheckerBoardPlatformUnkFC * 2; } -static void bhv_checkerboard_platform_loop_inner(void) { +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) { - case 0: - if (o->oBehParams2ndByte == 0) - o->oAction = 1; - else - o->oAction = 3; - break; - case 1: - checkerboard_plat_act_move_y(2, 10.0f, o->oCheckerBoardPlatformUnkFC); - break; - case 2: - checkerboard_plat_act_rotate(3, 512); - break; - case 3: - checkerboard_plat_act_move_y(4, -10.0f, o->oCheckerBoardPlatformUnkFC); - break; - case 4: - checkerboard_plat_act_rotate(1, -512); - break; + case 0: + if (o->oBehParams2ndByte == 0) + o->oAction = 1; + else + o->oAction = 3; + break; + case 1: + checkerboard_plat_act_move_y(2, 10.0f, o->oCheckerBoardPlatformUnkFC); + break; + case 2: + checkerboard_plat_act_rotate(3, 512); + break; + case 3: + checkerboard_plat_act_move_y(4, -10.0f, o->oCheckerBoardPlatformUnkFC); + break; + case 4: + checkerboard_plat_act_rotate(1, -512); + break; } o->oMoveAnglePitch += absi(o->oAngleVelPitch); o->oFaceAnglePitch += absi(o->oAngleVelPitch); @@ -86,18 +93,11 @@ static void bhv_checkerboard_platform_loop_inner(void) { o->oAngleVelPitch = 0; o->oFaceAnglePitch &= ~0x7FFF; cur_obj_move_using_fvel_and_gravity(); - } - else { + } else { cur_obj_move_using_fvel_and_gravity(); } -} - -void bhv_checkerboard_platform_loop(void) { - if (o->oDistanceToMario < 1000.0f) - cur_obj_play_sound_1(SOUND_ENV_ELEVATOR4); - - u32 loopLength = 132 + o->oCheckerBoardPlatformUnkFC * 2; - cur_obj_area_timer_loop(loopLength, bhv_checkerboard_platform_loop_inner); - - load_object_collision_model(); + + 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 a38be033b..f6f1daab3 100644 --- a/src/game/behaviors/ddd_pole.inc.c +++ b/src/game/behaviors/ddd_pole.inc.c @@ -6,9 +6,11 @@ void bhv_ddd_pole_init(void) { o->hitboxDownOffset = 100.0f; o->oDDDPoleMaxOffset = 100.0f * o->oBehParams2ndByte; } + o->areaTimer = 0; + o->areaTimerLoopLength = (((u16)o->oDDDPoleMaxOffset / 10) + 20) * 2; } -static void bhv_ddd_pole_update_inner(void) { +void bhv_ddd_pole_update(void) { if (o->oTimer > 20) { o->oDDDPoleOffset += o->oDDDPoleVel; @@ -20,8 +22,3 @@ static void bhv_ddd_pole_update_inner(void) { obj_set_dist_from_home(o->oDDDPoleOffset); } - -void bhv_ddd_pole_update(void) { - u32 loopLength = (((u16)o->oDDDPoleMaxOffset / 10) + 20) * 2; - cur_obj_area_timer_loop(loopLength, bhv_ddd_pole_update_inner); -} diff --git a/src/game/behaviors/rotating_platform.inc.c b/src/game/behaviors/rotating_platform.inc.c index 25cc9b941..5df523455 100644 --- a/src/game/behaviors/rotating_platform.inc.c +++ b/src/game/behaviors/rotating_platform.inc.c @@ -8,7 +8,13 @@ struct WFRotatingPlatformData sWFRotatingPlatformData[] = { { 0, 150, wdw_seg7_collision_070186B4, 1000 } }; -static void bhv_wf_rotating_wooden_platform_loop_inner(void) { +void bhv_wf_rotating_wooden_platform_init(void) { + o->areaTimer = 0; + o->areaTimerLoopLength = 380; +} + +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) { @@ -16,17 +22,16 @@ static void bhv_wf_rotating_wooden_platform_loop_inner(void) { } } else { o->oAngleVelYaw = 0x100; - if (o->oTimer > 126) + if (o->oTimer > 126) { o->oAction = 0; - cur_obj_play_sound_1(SOUND_ENV_ELEVATOR2); + } + if (lastNATUpdate) { + cur_obj_play_sound_1(SOUND_ENV_ELEVATOR2); + } } cur_obj_rotate_face_angle_using_vel(); } -void bhv_wf_rotating_wooden_platform_loop(void) { - cur_obj_area_timer_loop(380, bhv_wf_rotating_wooden_platform_loop_inner); -} - void bhv_rotating_platform_loop(void) { s8 sp1F = o->oBehParams >> 24; if (o->oTimer == 0) { diff --git a/src/game/behaviors/sliding_platform.inc.c b/src/game/behaviors/sliding_platform.inc.c index 3e2c14579..3ec8728fa 100644 --- a/src/game/behaviors/sliding_platform.inc.c +++ b/src/game/behaviors/sliding_platform.inc.c @@ -20,9 +20,11 @@ void bhv_wf_sliding_platform_init(void) { } o->oTimer = position_based_random_float_position() * 100.0f; + o->areaTimer = 0; + o->areaTimerLoopLength = 152; } -static void bhv_wf_sliding_platform_loop_inner(void) { +void bhv_wf_sliding_platform_loop(void) { switch (o->oAction) { case WF_SLID_BRICK_PTFM_ACT_WAIT: if (o->oTimer >= 101) { @@ -58,7 +60,3 @@ static void bhv_wf_sliding_platform_loop_inner(void) { break; } } - -void bhv_wf_sliding_platform_loop(void) { - cur_obj_area_timer_loop(152, bhv_wf_sliding_platform_loop_inner); -} diff --git a/src/game/behaviors/tower_platform.inc.c b/src/game/behaviors/tower_platform.inc.c index e872be809..7e5e1c001 100644 --- a/src/game/behaviors/tower_platform.inc.c +++ b/src/game/behaviors/tower_platform.inc.c @@ -54,7 +54,7 @@ void bhv_wf_elevator_tower_platform_loop(void) { } } -static void bhv_wf_sliding_tower_platform_loop_inner(void) { +void bhv_wf_sliding_tower_platform_loop(void) { s32 sp24 = o->oPlatformUnk110 / o->oPlatformUnk10C; switch (o->oAction) { case 0: @@ -82,13 +82,6 @@ static void bhv_wf_sliding_tower_platform_loop_inner(void) { } } -void bhv_wf_sliding_tower_platform_loop(void) { - u32 loopTime = 1 + (o->oPlatformUnk110 / o->oPlatformUnk10C); - loopTime *= 2; - loopTime += 1; - cur_obj_area_timer_loop(loopTime, bhv_wf_sliding_tower_platform_loop_inner); -} - void spawn_and_init_wf_platforms(s16 a, const BehaviorScript *bhv) { s16 yaw; struct Object *platform = spawn_object(o, a, bhv); @@ -100,6 +93,12 @@ void spawn_and_init_wf_platforms(s16 a, const BehaviorScript *bhv) { platform->oPlatformUnk110 = o->oPlatformSpawnerUnk104; platform->oPlatformUnk10C = o->oPlatformSpawnerUnk108; o->oPlatformSpawnerUnkF4++; + + u32 loopTime = 1 + (platform->oPlatformUnk110 / platform->oPlatformUnk10C); + loopTime *= 2; + loopTime += 1; + platform->areaTimer = 0; + platform->areaTimerLoopLength = loopTime; } void spawn_wf_platform_group(void) { diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index c6c73b8da..2b7b9600e 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -137,9 +137,11 @@ void turn_obj_away_from_surface(f32 velX, f32 velZ, f32 nX, UNUSED f32 nY, f32 n f32 *objYawZ) { *objYawX = (nZ * nZ - nX * nX) * velX / (nX * nX + nZ * nZ) - 2 * velZ * (nX * nZ) / (nX * nX + nZ * nZ); + if (isnan(*objYawX)) { *objYawX = 0; } *objYawZ = (nX * nX - nZ * nZ) * velZ / (nX * nX + nZ * nZ) - 2 * velX * (nX * nZ) / (nX * nX + nZ * nZ); + if (isnan(*objYawZ)) { *objYawZ = 0; } } /** diff --git a/src/game/spawn_object.c b/src/game/spawn_object.c index 09a1094c0..11773d00e 100644 --- a/src/game/spawn_object.c +++ b/src/game/spawn_object.c @@ -304,6 +304,10 @@ struct Object *allocate_object(struct ObjectNode *objList) { obj->header.gfx.pos[2] = -10000.0f; obj->header.gfx.throwMatrix = NULL; + obj->createdThroughNetwork = false; + obj->areaTimer = 0; + obj->areaTimerLoopLength = 0; + return obj; } @@ -363,9 +367,6 @@ struct Object *create_object(const BehaviorScript *bhvScript) { break; } - obj->createdThroughNetwork = false; - obj->areaTimer = 0; - return obj; } diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 9f21c9af6..3021c681a 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -257,6 +257,38 @@ void network_receive(u8 localIndex, u8* data, u16 dataLength) { packet_receive(&p); } +static void network_update_area_timer(void) { + bool brokenClock = false; +#ifdef DEVELOPMENT + static u16 skipClockCount = 0; + static u16 updateClockCount = 1; + if (updateClockCount > 0) { + updateClockCount--; + if (updateClockCount <= 0 || updateClockCount > 120) { + skipClockCount = rand() % 30; + } + } + else { + skipClockCount--; + if (skipClockCount <= 0 || skipClockCount > 60) { + updateClockCount = rand() % 120; + } + } + //brokenClock = (skipClockCount > 0); +#endif + if (!brokenClock) { + // update network area timer + u32 desiredNAT = gNetworkAreaTimer + 1; + gNetworkAreaTimer = (clock_elapsed_ticks() - gNetworkAreaTimerClock); + if (gNetworkAreaTimer < desiredNAT) { + gNetworkAreaTimer++; + } + else if (gNetworkAreaTimer > desiredNAT) { + gNetworkAreaTimer--; + } + } +} + void network_update(void) { // check for level loaded event if (networkLoadingLevel < LOADING_LEVEL_THRESHOLD) { @@ -268,13 +300,7 @@ void network_update(void) { } // update network area timer - u32 desiredNAT = gNetworkAreaTimer + 1; - gNetworkAreaTimer = (clock_elapsed_ticks() - gNetworkAreaTimerClock); - if (gNetworkAreaTimer < desiredNAT) { - gNetworkAreaTimer++; - } else if (gNetworkAreaTimer > desiredNAT) { - gNetworkAreaTimer--; - } + network_update_area_timer(); // send out update packets if (gNetworkType != NT_NONE) {