Rewrite the core of network area timer (yet again)

This commit is contained in:
MysterD 2021-08-10 18:21:10 -07:00
parent f82b6c7ad0
commit fecba91c5e
17 changed files with 147 additions and 161 deletions

View file

@ -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),

View file

@ -222,6 +222,7 @@ struct Object
/*0x25C*/ void *respawnInfo;
/*?????*/ u8 createdThroughNetwork;
/*?????*/ u32 areaTimer;
/*?????*/ u32 areaTimerLoopLength;
/*?????*/ u8 globalPlayerIndex;
};

View file

@ -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++;
// update network area timer
if (gCurrentObject->areaTimerLoopLength > 0) {
gCurrentObject->areaTimer++;
if (gCurrentObject->areaTimer < gNetworkAreaTimer) {
goto cur_obj_update_begin;
}
// 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);
}
}
@ -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));
}

View file

@ -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

View file

@ -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;
}

View file

@ -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];

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -50,9 +50,16 @@ 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) {
@ -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);
if (lastNATUpdate) {
load_object_collision_model();
}
}

View file

@ -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);
}

View file

@ -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;
}
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) {

View file

@ -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);
}

View file

@ -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) {

View file

@ -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; }
}
/**

View file

@ -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;
}

View file

@ -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) {