Properly dont sync cheat status in the racing penguin as well as get to the racing penguin

This commit is contained in:
EmeraldLockdown 2026-04-16 18:27:13 -05:00
parent 66879dbafa
commit cc8efecef7
8 changed files with 56 additions and 63 deletions

View file

@ -22,7 +22,7 @@ void piranha_plant_act_idle(void) {
cur_obj_scale(1);
#endif
struct Object* player = nearest_player_to_object(o);
struct Object *player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
if (distanceToPlayer < 1200.0f) {
o->oAction = PIRANHA_PLANT_ACT_SLEEPING;
@ -39,7 +39,6 @@ void piranha_plant_act_idle(void) {
* @return 1 if the player interacted with the Piranha Plant, 0 otherwise
*/
s32 piranha_plant_check_interactions(void) {
s32 i;
s32 interacted = 1;
if (o->oInteractStatus & INT_STATUS_INTERACTED) {
stop_secondary_music(50);
@ -47,7 +46,7 @@ s32 piranha_plant_check_interactions(void) {
cur_obj_play_sound_2(SOUND_OBJ2_PIRANHA_PLANT_DYING);
// Spawn 20 intangible purple particles that quickly dissipate.
for (i = 0; i < 20; i++) {
for (s32 i = 0; i < 20; i++) {
spawn_object(o, MODEL_PURPLE_MARBLE, bhvPurpleParticle);
}
o->oAction = PIRANHA_PLANT_ACT_ATTACKED;
@ -90,8 +89,8 @@ void piranha_plant_act_sleeping(void) {
o->oDamageOrCoinValue = 3;
#endif
struct Object* player = nearest_player_to_object(o);
struct Object* localPlayer = gMarioStates[0].marioObj;
struct Object *player = nearest_player_to_object(o);
struct Object *localPlayer = gMarioStates[0].marioObj;
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
s32 distanceToLocalPlayer = localPlayer ? dist_between_objects(o, localPlayer) : 10000;
if (distanceToPlayer < 400.0f) {
@ -123,8 +122,9 @@ void piranha_plant_act_woken_up(void) {
o->oDamageOrCoinValue = 3;
#endif
if (o->oTimer == 0)
if (o->oTimer == 0) {
stop_secondary_music(50);
}
if (piranha_plant_check_interactions() == 0) {
if (o->oTimer > 10) {
@ -211,7 +211,7 @@ void piranha_plant_act_shrink_and_die(void) {
* Wait for Mario to move far away, then respawn the Piranha Plant.
*/
void piranha_plant_act_wait_to_respawn(void) {
struct Object* player = nearest_player_to_object(o);
struct Object *player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
if (distanceToPlayer > 1200.0f) {
o->oAction = PIRANHA_PLANT_ACT_RESPAWN;
@ -258,8 +258,8 @@ static s8 sPiranhaPlantBiteSoundFrames[] = { 12, 28, 50, 64, -1 };
* Piranha Plant will move to the attacked state.
*/
void piranha_plant_act_biting(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
struct Object* player = marioState ? marioState->marioObj : NULL;
struct MarioState *marioState = nearest_mario_state_to_object(o);
struct Object *player = marioState ? marioState->marioObj : NULL;
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0;
@ -304,12 +304,14 @@ void piranha_plant_act_biting(void) {
* This is called from both the "stopped biting" state and the "sleeping" state.
*/
s32 mario_moving_fast_enough_to_make_piranha_plant_bite(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
struct MarioState *marioState = nearest_mario_state_to_object(o);
if (!marioState) { return FALSE; }
if (marioState->vel[1] > 10.0f)
if (marioState->vel[1] > 10.0f) {
return TRUE;
if (marioState->forwardVel > 10.0f)
}
if (marioState->forwardVel > 10.0f) {
return TRUE;
}
return FALSE;
}
@ -319,7 +321,7 @@ s32 mario_moving_fast_enough_to_make_piranha_plant_bite(void) {
* Plant start biting again. Otherwise, make it go back to sleep.
*/
void piranha_plant_act_stopped_biting(void) {
struct Object* player = nearest_player_to_object(o);
struct Object *player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
cur_obj_become_intangible();
cur_obj_init_animation_with_sound(6);
@ -361,6 +363,7 @@ void (*TablePiranhaPlantActions[])(void) = {
* Main loop for bhvPiranhaPlant.
*/
void bhv_piranha_plant_loop(void) {
// uses standard distance-based sync
if (!sync_object_is_initialized(o->oSyncID)) {
sync_object_init(o, 2000.0f);
sync_object_init_field(o, o->oAction);
@ -375,12 +378,13 @@ void bhv_piranha_plant_loop(void) {
CUR_OBJ_CALL_ACTION_FUNCTION(TablePiranhaPlantActions);
// In WF, hide all Piranha Plants once high enough up.
if (gCurrLevelNum == LEVEL_WF) {
struct Object* player = gMarioStates[0].marioObj;
struct Object *player = gMarioStates[0].marioObj;
f32 scalar = max(draw_distance_scalar(), 1.0f);
if (player->oPosY > 3400.0f * scalar)
if (player->oPosY > 3400.0f * scalar) {
cur_obj_hide();
else
} else {
cur_obj_unhide();
}
}
o->oInteractStatus = 0;
}

View file

@ -70,6 +70,7 @@ static void bhv_platform_track_on_sent_pre(void) {
* Init function for bhvPlatformOnTrack.
*/
void bhv_platform_on_track_init(void) {
// uses standard distance-based sync
if (!sync_object_is_initialized(o->oSyncID)) {
struct SyncObject* so = sync_object_init(o, 1000.0f);
if (so != NULL) {
@ -116,7 +117,6 @@ void bhv_platform_on_track_init(void) {
* wait for mario action.
*/
static void platform_on_track_act_init(void) {
s32 i;
o->oPlatformOnTrackPrevWaypoint = o->oPlatformOnTrackStartWaypoint;
o->oPlatformOnTrackPrevWaypointFlags = 0;
@ -136,7 +136,7 @@ static void platform_on_track_act_init(void) {
}
// Spawn track balls
for (i = 1; i < 6; i++) {
for (s32 i = 1; i < 6; i++) {
platform_on_track_update_pos_or_spawn_ball(i, o->oHomeX, o->oHomeY, o->oHomeZ);
}
@ -284,11 +284,10 @@ static void platform_on_track_act_fall(void) {
*/
static void platform_on_track_rock_ski_lift(void) {
s32 targetRoll = 0;
UNUSED s32 initialRoll = o->oFaceAngleRoll;
o->oFaceAngleRoll += (s32) o->oPlatformOnTrackSkiLiftRollVel;
struct Object* player = NULL;
struct Object *player = NULL;
for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; }
if (gMarioStates[i].marioObj->platform != o) { continue; }
@ -300,8 +299,7 @@ static void platform_on_track_rock_ski_lift(void) {
if (player != NULL) {
s32 distanceToPlayer = dist_between_objects(o, player);
s32 angleToPlayer = obj_angle_to_object(o, player);
targetRoll = o->oForwardVel * sins(o->oMoveAngleYaw) * -50.0f
+ (s32)(distanceToPlayer * sins(angleToPlayer - o->oFaceAngleYaw) * -4.0f);
targetRoll = o->oForwardVel * sins(o->oMoveAngleYaw) * -50.0f + (s32)(distanceToPlayer * sins(angleToPlayer - o->oFaceAngleYaw) * -4.0f);
}
oscillate_toward(

View file

@ -172,12 +172,11 @@ static void pokey_on_received_post(UNUSED u8 localIndex) {
*/
static void pokey_act_uninitialized(void) {
struct Object *bodyPart;
s32 i;
s16 partModel;
partModel = MODEL_POKEY_HEAD;
for (i = 0; i < 5; i++) {
for (s32 i = 0; i < 5; i++) {
// Spawn body parts at y offsets 480, 360, 240, 120, 0
// behavior param 0 = head, 4 = lowest body part
bodyPart = spawn_object_relative(i, 0, -i * 120 + 480, 0, o, partModel, bhvPokeyBodyPart);
@ -194,6 +193,7 @@ static void pokey_act_uninitialized(void) {
o->oPokeyBottomBodyPartSize = 1.0f;
o->oAction = POKEY_ACT_WANDER;
// uses standard distance-based sync
if (!sync_object_is_initialized(o->oSyncID)) {
struct SyncObject* so = sync_object_init(o, 4000.0f);
if (so) {
@ -216,7 +216,7 @@ static void pokey_act_uninitialized(void) {
* if mario gets too close, then shy away from him.
*/
static void pokey_act_wander(void) {
struct Object* player = nearest_player_to_object(o);
struct Object *player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0;
@ -260,8 +260,7 @@ static void pokey_act_wander(void) {
}
if (o->oPokeyTurningAwayFromWall) {
o->oPokeyTurningAwayFromWall =
obj_resolve_collisions_and_turn(o->oPokeyTargetYaw, 0x200);
o->oPokeyTurningAwayFromWall = obj_resolve_collisions_and_turn(o->oPokeyTargetYaw, 0x200);
} else {
// If far from home, turn back toward home
if (distanceToPlayer >= 25000.0f) {

View file

@ -7,6 +7,7 @@
*/
void bhv_purple_switch_loop(void) {
// uses event based syncing system. Syncs when the button is pressed
if (!sync_object_is_initialized(o->oSyncID)) {
sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS);
sync_object_init_field(o, o->oAction);
@ -22,7 +23,6 @@ void bhv_purple_switch_loop(void) {
}
}
UNUSED s32 unused;
switch (o->oAction) {
/**
* Set the switch's model and scale. If Mario is standing near the

View file

@ -15,9 +15,10 @@ void bhv_pyramid_elevator_init(void) {
if (ball == NULL) { continue; }
ball->oPosY = 4600 - i * 460;
}
// uses event based sync system. Sends when the elevator starts moving and reaches the bottom
if (!sync_object_is_initialized(o->oSyncID)) {
struct SyncObject* so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS);
struct SyncObject *so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
sync_object_init_field(o, o->oPrevAction);
sync_object_init_field(o, o->oAction);
@ -78,7 +79,7 @@ void bhv_pyramid_elevator_loop(void) {
network_send_object(o);
}
break;
/**
* The elevator is now at the bottom and finished it's moving
* We will no longer move from this point.

View file

@ -25,8 +25,6 @@ void bhv_pyramid_top_init(void) {
* fragments in the process.
*/
void bhv_pyramid_top_spinning(void) {
struct Object *pyramidFragment;
// (TODO: What is this doing)
o->oPosX = o->oHomeX + sins(o->oTimer * 0x4000) * 40.0f;
@ -48,7 +46,7 @@ void bhv_pyramid_top_spinning(void) {
// Every frame until 90 frames have passed, generate a pyramid fragment
// with a random velocity and angle.
if (o->oTimer < 90) {
pyramidFragment = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPyramidTopFragment);
struct Object *pyramidFragment = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPyramidTopFragment);
if (pyramidFragment != NULL) {
pyramidFragment->oForwardVel = random_float() * 10.0f + 20.0f;
pyramidFragment->oMoveAngleYaw = random_u16();
@ -88,6 +86,7 @@ void bhv_pyramid_top_explode(void) {
}
void bhv_pyramid_top_loop(void) {
// uses an event based sync system. Syncs when the puzzle is solved
if (!sync_object_is_initialized(o->oSyncID)) {
struct SyncObject *so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
@ -97,7 +96,7 @@ void bhv_pyramid_top_loop(void) {
sync_object_init_field(o, o->oTimer);
}
}
switch (o->oAction) {
case PYRAMID_TOP_ACT_CHECK_IF_SOLVED:
if (o->oPyramidTopPillarsTouched == 4) {

View file

@ -11,6 +11,7 @@
* positions.
*/
void bhv_ssl_moving_pyramid_wall_init(void) {
// synced via area timer
o->areaTimerType = AREA_TIMER_TYPE_LOOP;
o->areaTimer = 0;
o->areaTimerDuration = 200;

View file

@ -1,7 +1,7 @@
struct RacingPenguinData {
enum DialogId* text;
f32* radius;
f32* height;
f32 *radius;
f32 *height;
};
static struct RacingPenguinData sRacingPenguinData[] = {
@ -24,7 +24,7 @@ static void bhv_racing_penguin_the_quick_on_sent_pre(void) {
penguinPathedPrevWaypoint = ((void*)o->oPathedPrevWaypoint - path) / sizeof(struct Waypoint*);
}
void bhv_racing_penguin_the_quick_override_ownership(u8* shouldOverride, u8* shouldOwn) {
void bhv_racing_penguin_the_quick_override_ownership(u8 *shouldOverride, u8 *shouldOwn) {
*shouldOverride = TRUE;
*shouldOwn = (get_network_player_smallest_global() == gNetworkPlayerLocal);
}
@ -40,18 +40,20 @@ void bhv_racing_penguin_run_once(void) {
void bhv_racing_penguin_init(void) {
if (gMarioStates[0].numStars == 120) {
// massive penguin
cur_obj_scale(8.0f);
o->header.gfx.scale[1] = 5.0f;
o->oBehParams2ndByte = 1;
}
struct Object* objFinishLine = cur_obj_nearest_object_with_behavior(bhvPenguinRaceFinishLine);
struct Object *objFinishLine = cur_obj_nearest_object_with_behavior(bhvPenguinRaceFinishLine);
if (objFinishLine) { objFinishLine->parentObj = o; }
struct Object* objShortcutCheck = cur_obj_nearest_object_with_behavior(bhvPenguinRaceShortcutCheck);
struct Object *objShortcutCheck = cur_obj_nearest_object_with_behavior(bhvPenguinRaceShortcutCheck);
if (objShortcutCheck) { objShortcutCheck->parentObj = o; }
struct SyncObject* so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS);
// syncs using a event based sync system.
struct SyncObject *so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
so->on_received_post = bhv_racing_penguin_the_quick_on_received_post;
so->on_sent_pre = bhv_racing_penguin_the_quick_on_sent_pre;
@ -85,7 +87,7 @@ void bhv_racing_penguin_init(void) {
}
static void racing_penguin_act_wait_for_mario(void) {
struct Object* player = nearest_player_to_object(o);
struct Object *player = nearest_player_to_object(o);
if (!player) { return; }
if (o->oTimer > o->oRacingPenguinInitTextCooldown && o->oPosY - player->oPosY <= 0.0f
&& cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 400.0f, 400.0f)) {
@ -109,8 +111,7 @@ static void racing_penguin_act_show_init_text(void) {
child = cur_obj_nearest_object_with_behavior(bhvPenguinRaceShortcutCheck);
child->parentObj = o;
o->oPathedStartWaypoint = o->oPathedPrevWaypoint =
segmented_to_virtual(gBehaviorValues.trajectories.RacingPenguinTrajectory);
o->oPathedStartWaypoint = o->oPathedPrevWaypoint = segmented_to_virtual(gBehaviorValues.trajectories.RacingPenguinTrajectory);
o->oPathedPrevWaypointFlags = 0;
o->oAction = RACING_PENGUIN_ACT_PREPARE_FOR_RACE;
@ -139,7 +140,7 @@ static void racing_penguin_act_race(void) {
// prevent segfault / error state
if (o->oPathedStartWaypoint == NULL) {
struct Object* child = NULL;
struct Object *child = NULL;
child = cur_obj_nearest_object_with_behavior(bhvPenguinRaceFinishLine);
if (child) { child->parentObj = o; }
@ -150,13 +151,13 @@ static void racing_penguin_act_race(void) {
o->oPathedPrevWaypointFlags = 0;
}
struct Waypoint* lastPrevWaypoint = o->oPathedPrevWaypoint;
struct Waypoint *lastPrevWaypoint = o->oPathedPrevWaypoint;
if (cur_obj_follow_path(0) == PATH_REACHED_END) {
o->oRacingPenguinReachedBottom = TRUE;
o->oAction = RACING_PENGUIN_ACT_FINISH_RACE;
if (sync_object_is_owned_locally(o->oSyncID)) { network_send_object(o); }
} else {
struct Object* player = nearest_player_to_object(o);
struct Object *player = nearest_player_to_object(o);
targetSpeed = player ? (o->oPosY - player->oPosY) : o->oPosY;
minSpeed = 70.0f;
@ -184,15 +185,7 @@ static void racing_penguin_act_race(void) {
}
}
// Removed the in-air shortcut check due to inconsistent detection and the
// fact that one player can fall off while the other player completes the
// race.
/*u8 isInAir = FALSE;
for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; }
isInAir = isInAir || mario_is_in_air_action(&gMarioStates[i]);
}
u8 isInAir = mario_is_in_air_action(&gMarioStates[0]);
if (isInAir) {
if (o->oTimer > 60 && !o->oRacingPenguinMarioCheated) {
o->oRacingPenguinMarioCheated = TRUE;
@ -200,7 +193,7 @@ static void racing_penguin_act_race(void) {
}
} else {
o->oTimer = 0;
}*/
}
if (lastPrevWaypoint != o->oPathedPrevWaypoint) {
if (sync_object_is_owned_locally(o->oSyncID)) { network_send_object(o); }
@ -233,7 +226,6 @@ static void racing_penguin_act_show_final_text(void) {
if (o->oRacingPenguinMarioWon) {
if (o->oRacingPenguinMarioCheated) {
o->oRacingPenguinFinalTextbox = gBehaviorValues.dialogs.RacingPenguinCheatDialog;
o->oRacingPenguinMarioWon = FALSE;
} else {
o->oRacingPenguinFinalTextbox = gBehaviorValues.dialogs.RacingPenguinWinDialog;
}
@ -255,9 +247,8 @@ static void racing_penguin_act_show_final_text(void) {
o->oRacingPenguinFinalTextbox = -1;
o->oTimer = 0;
}
} else if (o->oRacingPenguinMarioWon) {
f32* starPos = gLevelValues.starPositions.RacingPenguinStarPos;
} else if (o->oRacingPenguinMarioWon && !o->oRacingPenguinMarioCheated) {
f32 *starPos = gLevelValues.starPositions.RacingPenguinStarPos;
#ifdef VERSION_JP
spawn_default_star(starPos[0], starPos[1], starPos[2]);
#else
@ -296,7 +287,7 @@ void bhv_racing_penguin_update(void) {
}
void bhv_penguin_race_finish_line_update(void) {
struct Object* player = nearest_player_to_object(o);
struct Object *player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
if (!o->parentObj) {
return;
@ -312,7 +303,7 @@ void bhv_penguin_race_finish_line_update(void) {
}
void bhv_penguin_race_shortcut_check_update(void) {
struct Object* player = nearest_player_to_object(o);
struct Object *player = gMarioStates[0].marioObj;
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
if (distanceToPlayer < 500.0f && o->parentObj && !o->parentObj->oRacingPenguinMarioCheated) {
o->parentObj->oRacingPenguinMarioCheated = TRUE;