Resynchronized checkerboard elevators to use area timer

This commit is contained in:
MysterD 2021-06-14 20:29:08 -07:00
parent e7d0f8ec8b
commit ef2287a5d5
16 changed files with 171 additions and 97 deletions

View file

@ -3994,6 +3994,7 @@
<ClCompile Include="..\src\pc\network\packets\packet_reservation_use.c" />
<ClCompile Include="..\src\pc\network\packets\packet_save_file.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level_spawn_info.c" />
<ClCompile Include="..\src\pc\network\packets\packet_save_set_flag.c" />
<ClCompile Include="..\src\pc\network\packets\packet_spawn_objects.c" />
<ClCompile Include="..\src\pc\network\packets\packet_spawn_star.c" />
<ClCompile Include="..\src\pc\network\packets\packet_sync_valid.c" />

View file

@ -15141,6 +15141,9 @@
<ClCompile Include="..\src\pc\network\reservation_area.c">
<Filter>Source Files\src\pc\network</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\network\packets\packet_save_set_flag.c">
<Filter>Source Files\src\pc\network\packets</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\actors\common0.h">

View file

@ -376,6 +376,7 @@
#define /*0x0F8*/ oCheckerBoardPlatformUnkF8 OBJECT_FIELD_S32(0x1C) // oAction like
#define /*0x0FC*/ oCheckerBoardPlatformUnkFC OBJECT_FIELD_S32(0x1D)
#define /*0x1AC*/ oCheckerBoardPlatformUnk1AC OBJECT_FIELD_F32(0x49)
#define /*0x1B0*/ oCheckerBoardPlatformTimer OBJECT_FIELD_U32(0x4A)
/* Cheep Cheep */
#define /*0x0F4*/ oCheepCheepUnkF4 OBJECT_FIELD_F32(0x1B)

View file

@ -1052,3 +1052,68 @@ 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);
}
}

View file

@ -26,5 +26,6 @@ s32 random_sign(void);
void stub_behavior_script_2(void);
void cur_obj_update(void);
void cur_obj_fake_update(void);
#endif // BEHAVIOR_SCRIPT_H

View file

@ -260,15 +260,15 @@ void (*sBowserPuzzlePieceActions[])(void) = {
void bhv_lll_bowser_puzzle_piece_loop(void) {
// make sure we're loaded and synchronized
if (!gNetworkLevelLoaded) {
if (!gNetworkAreaLoaded) {
o->oTimer = 0;
return;
} else if (o->oBowserPuzzlePieceTimer == 0 && (gNetworkLevelTimer - o->oBowserPuzzlePieceTimer) >= 650) {
o->oBowserPuzzlePieceTimer = ((gNetworkLevelTimer - o->oBowserPuzzlePieceTimer) / 650) * 650;
} else if (o->oBowserPuzzlePieceTimer == 0 && (gNetworkAreaTimer - o->oBowserPuzzlePieceTimer) >= 650) {
o->oBowserPuzzlePieceTimer = ((gNetworkAreaTimer - o->oBowserPuzzlePieceTimer) / 650) * 650;
o->oTimer = 0;
}
while (o->oBowserPuzzlePieceTimer < gNetworkLevelTimer) {
while (o->oBowserPuzzlePieceTimer < gNetworkAreaTimer) {
bhv_lll_bowser_puzzle_piece_update();
cur_obj_call_action_function(sBowserPuzzlePieceActions);
@ -278,8 +278,8 @@ void bhv_lll_bowser_puzzle_piece_loop(void) {
o->oPosZ = o->oBowserPuzzlePieceOffsetZ + o->oHomeZ;
o->oBowserPuzzlePieceTimer++;
if (o->oBowserPuzzlePieceTimer < gNetworkLevelTimer) {
o->oTimer++;
if (o->oBowserPuzzlePieceTimer < gNetworkAreaTimer) {
cur_obj_fake_update();
}
}
}

View file

@ -4,7 +4,7 @@ void bhv_cannon_closed_init(void) {
struct Object *cannon;
if (save_file_is_cannon_unlocked() == 1) {
if (!gNetworkLevelLoaded || gNetworkType == NT_SERVER) {
if (!gNetworkAreaLoaded || gNetworkType == NT_SERVER) {
// If the cannon is open, spawn a cannon and despawn the object.
cannon = spawn_object(o, MODEL_CANNON_BASE, bhvCannon);
cannon->parentObj = cannon;
@ -12,7 +12,7 @@ void bhv_cannon_closed_init(void) {
cannon->oPosX = o->oHomeX;
cannon->oPosY = o->oHomeY;
cannon->oPosZ = o->oHomeZ;
if (gNetworkLevelLoaded) {
if (gNetworkAreaLoaded) {
network_set_sync_id(cannon);
struct Object* spawn_objects[] = { cannon };
u32 models[] = { MODEL_CANNON_BASE };

View file

@ -528,7 +528,7 @@ void bhv_wooden_post_update(void) {
// chomp
o->oWoodenPostOffsetY = -190.0f;
if (o->parentObj != o) {
if (gNetworkLevelSyncing) {
if (gNetworkAreaSyncing) {
// force chain chomp cutscene ending
o->parentObj->oAction = CHAIN_CHOMP_ACT_UNLOAD_CHAIN;
o->parentObj->oChainChompReleaseStatus = CHAIN_CHOMP_RELEASED_END_CUTSCENE;

View file

@ -5,9 +5,6 @@ struct Struct8032F754 D_8032F754[] = { { 145, { 0.7f, 1.5f, 0.7f }, 7.0f },
void bhv_checkerboard_elevator_group_init(void) {
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
struct SyncObject* so = network_init_object(o, 1000.0f);
so->hasStandardFields = FALSE;
so->maxUpdateRate = 5.0f;
s32 sp3C;
s32 sp38;
s32 sp34;
@ -26,26 +23,9 @@ void bhv_checkerboard_elevator_group_init(void) {
sp2C = spawn_object_relative(i, 0, i * sp3C, sp38, o, MODEL_CHECKERBOARD_PLATFORM,
bhvCheckerboardPlatformSub);
sp2C->oCheckerBoardPlatformUnk1AC = D_8032F754[sp34].unk2;
sp2C->oTimer = 0;
sp2C->oCheckerBoardPlatformTimer = 0;
vec3f_copy_2(sp2C->header.gfx.scale, D_8032F754[sp34].unk1);
network_init_object_field(o, &sp2C->oMoveAnglePitch);
network_init_object_field(o, &sp2C->oMoveAngleYaw);
network_init_object_field(o, &sp2C->oFaceAnglePitch);
network_init_object_field(o, &sp2C->oFaceAngleYaw);
network_init_object_field(o, &sp2C->oAngleVelPitch);
network_init_object_field(o, &sp2C->oAngleVelYaw);
network_init_object_field(o, &sp2C->oForwardVel);
network_init_object_field(o, &sp2C->oPosX);
network_init_object_field(o, &sp2C->oPosY);
network_init_object_field(o, &sp2C->oPosZ);
network_init_object_field(o, &sp2C->oVelX);
network_init_object_field(o, &sp2C->oVelY);
network_init_object_field(o, &sp2C->oVelZ);
network_init_object_field(o, &sp2C->oAction);
network_init_object_field(o, &sp2C->oPrevAction);
network_init_object_field(o, &sp2C->oTimer);
network_init_object_field(o, &sp2C->oCheckerBoardPlatformUnkF8);
network_init_object_field(o, &sp2C->oCheckerBoardPlatformUnkFC);
}
}
@ -63,8 +43,9 @@ void checkerboard_plat_act_move_y(UNUSED s32 unused, f32 vel, s32 a2) {
void checkerboard_plat_act_rotate(s32 a0, s16 a1) {
o->oVelY = 0.0f;
o->oAngleVelPitch = a1;
if (o->oTimer + 1 == 0x8000 / absi(a1))
if (o->oTimer + 1 == 0x8000 / absi(a1)) {
o->oAction = a0;
}
o->oCheckerBoardPlatformUnkF8 = a0;
}
@ -73,42 +54,65 @@ void bhv_checkerboard_platform_init(void) {
}
void bhv_checkerboard_platform_loop(void) {
f32 sp24 = o->oCheckerBoardPlatformUnk1AC;
o->oCheckerBoardPlatformUnkF8 = 0;
// make sure we're loaded and synchronized
if (!gNetworkAreaLoaded) {
o->oTimer = 0;
o->oCheckerBoardPlatformTimer = 0;
return;
} else {
u32 loopLength = 132 + o->oCheckerBoardPlatformUnkFC * 2;
if (o->oCheckerBoardPlatformTimer == 0 && (gNetworkAreaTimer - o->oCheckerBoardPlatformTimer) >= loopLength) {
o->oTimer = 0;
o->oCheckerBoardPlatformTimer = ((gNetworkAreaTimer - o->oCheckerBoardPlatformTimer) / loopLength) * loopLength;
}
}
if (o->oDistanceToMario < 1000.0f)
cur_obj_play_sound_1(SOUND_ENV_ELEVATOR4);
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;
while (o->oCheckerBoardPlatformTimer < gNetworkAreaTimer) {
s32 oldAction = o->oAction;
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;
}
o->oMoveAnglePitch += absi(o->oAngleVelPitch);
o->oFaceAnglePitch += absi(o->oAngleVelPitch);
o->oFaceAngleYaw = o->oMoveAngleYaw;
if (o->oMoveAnglePitch != 0) {
o->oForwardVel = signum_positive(o->oAngleVelPitch) * sins(o->oMoveAnglePitch) * sp24;
o->oVelY = signum_positive(o->oAngleVelPitch) * coss(o->oMoveAnglePitch) * sp24;
}
if (o->oCheckerBoardPlatformUnkF8 == 1) {
o->oAngleVelPitch = 0;
o->oFaceAnglePitch &= ~0x7FFF;
cur_obj_move_using_fvel_and_gravity();
} else
cur_obj_move_using_fvel_and_gravity();
o->oCheckerBoardPlatformTimer++;
if (o->oCheckerBoardPlatformTimer < gNetworkAreaTimer) {
cur_obj_fake_update();
}
}
o->oMoveAnglePitch += absi(o->oAngleVelPitch);
o->oFaceAnglePitch += absi(o->oAngleVelPitch);
o->oFaceAngleYaw = o->oMoveAngleYaw;
if (o->oMoveAnglePitch != 0) {
o->oForwardVel = signum_positive(o->oAngleVelPitch) * sins(o->oMoveAnglePitch) * sp24;
o->oVelY = signum_positive(o->oAngleVelPitch) * coss(o->oMoveAnglePitch) * sp24;
}
if (o->oCheckerBoardPlatformUnkF8 == 1) {
o->oAngleVelPitch = 0;
o->oFaceAnglePitch &= ~0x7FFF;
cur_obj_move_using_fvel_and_gravity();
} else
cur_obj_move_using_fvel_and_gravity();
load_object_collision_model();
}

View file

@ -24,7 +24,7 @@ void bhv_spawned_star_init(void) {
// exclamation box stars are not sent through the normal exclamation box
// path due to jankiness in oBehParams. Send the spawn event here instead.
u8 spawnedFromExclamationBox = (o->parentObj != NULL && o->parentObj->behavior == bhvExclamationBox);
if (gNetworkLevelLoaded && spawnedFromExclamationBox) {
if (gNetworkAreaLoaded && spawnedFromExclamationBox) {
o->parentObj = o;
struct Object* spawn_objects[] = { o };
u32 models[] = { MODEL_STAR };

View file

@ -13,7 +13,7 @@
#ifdef DEBUG
static u8 warpToLevel = LEVEL_LLL;
static u8 warpToLevel = LEVEL_BOB;
#define SCANCODE_0 0x0B
#define SCANCODE_1 0x02

View file

@ -25,9 +25,9 @@ struct NetworkSystem* gNetworkSystem = &gNetworkSystemSocket;
#define LOADING_LEVEL_THRESHOLD 10
u16 networkLoadingLevel = 0;
bool gNetworkLevelLoaded = false;
bool gNetworkLevelSyncing = true;
u32 gNetworkLevelTimer = 0;
bool gNetworkAreaLoaded = false;
bool gNetworkAreaSyncing = true;
u32 gNetworkAreaTimer = 0;
clock_t gLastNetworkSend = 0;
struct StringLinkedList gRegisteredMods = { 0 };
@ -87,15 +87,15 @@ bool network_init(enum NetworkType inNetworkType) {
return true;
}
void network_on_init_level(void) {
void network_on_init_area(void) {
// reset loading timer
networkLoadingLevel = 0;
gNetworkLevelLoaded = false;
gNetworkLevelSyncing = true;
gNetworkLevelTimer = 0;
gNetworkAreaLoaded = false;
gNetworkAreaSyncing = true;
gNetworkAreaTimer = 0;
}
void network_on_loaded_level(void) {
void network_on_loaded_area(void) {
area_remove_sync_ids_clear();
struct NetworkPlayer* np = gNetworkPlayerLocal;
if (np != NULL) {
@ -228,13 +228,13 @@ void network_update(void) {
// check for level loaded event
if (networkLoadingLevel < LOADING_LEVEL_THRESHOLD) {
networkLoadingLevel++;
if (!gNetworkLevelLoaded && networkLoadingLevel >= LOADING_LEVEL_THRESHOLD) {
gNetworkLevelLoaded = true;
gNetworkLevelTimer = 0;
network_on_loaded_level();
if (!gNetworkAreaLoaded && networkLoadingLevel >= LOADING_LEVEL_THRESHOLD) {
gNetworkAreaLoaded = true;
gNetworkAreaTimer = 0;
network_on_loaded_area();
}
} else if (gNetworkLevelLoaded) {
gNetworkLevelTimer++;
} else if (gNetworkAreaLoaded) {
gNetworkAreaTimer++;
}
// send out update packets

View file

@ -80,9 +80,9 @@ struct ServerSettings {
// Networking-specific externs
extern struct NetworkSystem* gNetworkSystem;
extern enum NetworkType gNetworkType;
extern bool gNetworkLevelLoaded;
extern bool gNetworkLevelSyncing;
extern u32 gNetworkLevelTimer;
extern bool gNetworkAreaLoaded;
extern bool gNetworkAreaSyncing;
extern u32 gNetworkAreaTimer;
extern struct SyncObject gSyncObjects[];
extern struct ServerSettings gServerSettings;
extern clock_t gLastNetworkSend;
@ -91,8 +91,8 @@ extern struct StringLinkedList gRegisteredMods;
// network.c
void network_set_system(enum NetworkSystemType nsType);
bool network_init(enum NetworkType inNetworkType);
void network_on_init_level(void);
void network_on_loaded_level(void);
void network_on_init_area(void);
void network_on_loaded_area(void);
void network_send_to(u8 localIndex, struct Packet* p);
void network_send(struct Packet* p);
void network_receive(u8 localIndex, u8* data, u16 dataLength);

View file

@ -44,7 +44,7 @@ void network_send_area(struct NetworkPlayer* toNp) {
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
// area variables
packet_write(&p, &gNetworkLevelTimer, sizeof(u32));
packet_write(&p, &gNetworkAreaTimer, sizeof(u32));
// write sync id removals
packet_write(&p, &sRemoveSyncIdsIndex, sizeof(u8));
@ -132,16 +132,15 @@ void network_receive_area(struct Packet* p) {
packet_read(p, &levelNum, sizeof(s16));
packet_read(p, &areaIndex, sizeof(s16));
// read area variables
packet_read(p, &gNetworkLevelTimer, sizeof(u32));
extern s16 gCurrCourseNum, gCurrActStarNum, gCurrLevelNum;
if (courseNum != gCurrCourseNum || actNum != gCurrActStarNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
LOG_ERROR("rx area: received an improper location");
return;
}
// read area variables
packet_read(p, &gNetworkAreaTimer, sizeof(u32));
// read removed sync ids
area_remove_sync_ids_clear();
packet_read(p, &sRemoveSyncIdsIndex, sizeof(u8));

View file

@ -139,7 +139,7 @@ bool network_sync_object_initialized(struct Object* o) {
void network_clear_sync_objects(void) {
sNextSyncId = 0;
network_on_init_level();
network_on_init_area();
for (u16 i = 0; i < MAX_SYNC_OBJECTS; i++) {
network_forget_sync_object(&gSyncObjects[i]);
}
@ -149,7 +149,7 @@ void network_set_sync_id(struct Object* o) {
if (o->oSyncID != 0) { return; }
u8 syncId = 0;
if (!gNetworkLevelLoaded) {
if (!gNetworkAreaLoaded) {
// while loading, just fill in sync ids from 1 to MAX_SYNC_OBJECTS
for (int i = 1; i < MAX_SYNC_OBJECTS; i++) {
sNextSyncId++;
@ -168,7 +168,7 @@ void network_set_sync_id(struct Object* o) {
o->oSyncID = syncId;
if (gNetworkLevelLoaded) {
if (gNetworkAreaLoaded) {
LOG_INFO("set sync id for object w/behavior %d", get_id_from_behavior(o->behavior));
}

View file

@ -10,7 +10,7 @@ void network_send_sync_valid(struct NetworkPlayer* toNp) {
if (toNp == gNetworkPlayerLocal) {
// the player is the server, no need to send it
gNetworkLevelSyncing = false;
gNetworkAreaSyncing = false;
return;
}
@ -62,5 +62,5 @@ void network_receive_sync_valid(struct Packet* p) {
}
// we're no longer syncing
gNetworkLevelSyncing = false;
gNetworkAreaSyncing = false;
}