From 6510f3928cab7ebc5fafe7480a574234147e3123 Mon Sep 17 00:00:00 2001 From: EmeraldLockdown <86802223+EmeraldLoc@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:37:30 -0500 Subject: [PATCH] Fix cutscenes, syncing issues, and more (Yoshi!) (#1109) * Fixes * Lots more changes * Yoshi :D * Remove some unecessary changes * Oops * Remove temp code * Revert changes made to king bobomb, will be handled in #1196 * copied from main not dev, oops * Address review and do a minor improvement * Nuke that --- autogen/convert_structs.py | 2 +- autogen/lua_definitions/constants.lua | 6 + autogen/lua_definitions/functions.lua | 2 +- autogen/lua_definitions/structs.lua | 2 +- data/dynos_bin_behavior.cpp | 2 +- docs/lua/constants.md | 2 + docs/lua/functions-5.md | 2 +- docs/lua/structs.md | 2 +- include/object_constants.h | 4 +- include/object_fields.h | 2 +- src/audio/external.c | 88 ++++----- src/game/behaviors/bowser.inc.c | 16 +- src/game/behaviors/camera_lakitu.inc.c | 21 +- src/game/behaviors/spawn_star.inc.c | 2 +- src/game/behaviors/ukiki.inc.c | 2 +- src/game/behaviors/water_ring.inc.c | 9 +- src/game/behaviors/yoshi.inc.c | 263 +++++++++++++++++-------- src/game/level_update.c | 2 - src/game/mario_actions_cutscene.c | 12 +- src/game/obj_behaviors.c | 8 +- src/pc/lua/smlua_cobject_autogen.c | 6 +- src/pc/lua/smlua_constants_autogen.c | 2 + src/pc/lua/smlua_functions_autogen.c | 21 ++ src/pc/network/packets/packet_level.c | 5 +- src/pc/network/packets/packet_player.c | 3 + 25 files changed, 312 insertions(+), 174 deletions(-) diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 3a88390ec..166bfe4fd 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -148,7 +148,7 @@ override_field_immutable = { } override_field_version_excludes = { - "oCameraLakituUnk104": "VERSION_JP", + "oCameraLakituMusicPlayed": "VERSION_JP", "oCoinUnk1B0": "VERSION_JP", } diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 4f14dfdaf..5cb601871 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -5635,6 +5635,12 @@ YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN = 4 --- @type integer YOSHI_ACT_GIVE_PRESENT = 5 +--- @type integer +YOSHI_ACT_GONE = 6 + +--- @type integer +YOSHI_ACT_REAPPEAR = 7 + --- @type integer YOSHI_ACT_CREDITS = 10 diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index a57d791ed..592157783 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -7992,7 +7992,7 @@ function network_discord_id_from_local_index(localIndex) -- ... end ---- Resets Yoshi as being alive +--- Marks Yoshi as alive function set_yoshi_as_not_dead() -- ... end diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index c39734496..4f3f887f4 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -1724,7 +1724,7 @@ --- @field public oCameraLakituSpeed number --- @field public oCameraLakituCircleRadius number --- @field public oCameraLakituFinishedDialog integer ---- @field public oCameraLakituUnk104 integer +--- @field public oCameraLakituMusicPlayed integer --- @field public oCameraLakituPitchVel integer --- @field public oCameraLakituYawVel integer --- @field public oEnemyLakituNumSpinies integer diff --git a/data/dynos_bin_behavior.cpp b/data/dynos_bin_behavior.cpp index 805a31ac8..73736a424 100644 --- a/data/dynos_bin_behavior.cpp +++ b/data/dynos_bin_behavior.cpp @@ -1374,7 +1374,7 @@ s64 DynOS_Bhv_ParseBehaviorScriptConstants(const String &_Arg, bool *found) { bhv_constant(oCameraLakituCircleRadius); bhv_constant(oCameraLakituFinishedDialog); #ifndef VERSION_JP - bhv_constant(oCameraLakituUnk104); + bhv_constant(oCameraLakituMusicPlayed); #endif bhv_constant(oCameraLakituPitchVel); bhv_constant(oCameraLakituYawVel); diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 2f67ef821..c70da9237 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -2556,6 +2556,8 @@ - YOSHI_ACT_WALK_JUMP_OFF_ROOF - YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN - YOSHI_ACT_GIVE_PRESENT +- YOSHI_ACT_GONE +- YOSHI_ACT_REAPPEAR - YOSHI_ACT_CREDITS - KOOPA_UNSHELLED_ACT_RUN - KOOPA_UNSHELLED_ACT_DIVE diff --git a/docs/lua/functions-5.md b/docs/lua/functions-5.md index 92990911d..e8822093a 100644 --- a/docs/lua/functions-5.md +++ b/docs/lua/functions-5.md @@ -2882,7 +2882,7 @@ Gets a Discord ID corresponding to the network player with `localIndex` ## [set_yoshi_as_not_dead](#set_yoshi_as_not_dead) ### Description -Resets Yoshi as being alive +Marks Yoshi as alive ### Lua Example `set_yoshi_as_not_dead()` diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 8fc531350..d7be1dc75 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -2322,7 +2322,7 @@ | oCameraLakituSpeed | `number` | | | oCameraLakituCircleRadius | `number` | | | oCameraLakituFinishedDialog | `integer` | | -| oCameraLakituUnk104 | `integer` | | +| oCameraLakituMusicPlayed | `integer` | | | oCameraLakituPitchVel | `integer` | | | oCameraLakituYawVel | `integer` | | | oEnemyLakituNumSpinies | `integer` | | diff --git a/include/object_constants.h b/include/object_constants.h index 7c5d11289..720955e83 100644 --- a/include/object_constants.h +++ b/include/object_constants.h @@ -197,7 +197,7 @@ /* oAction */ #define FISH_SPAWNER_ACT_SPAWN 0 #define FISH_SPAWNER_ACT_IDLE 1 - #define FISH_SPAWNER_ACT_RESPAWN 2 + #define FISH_SPAWNER_ACT_RESPAWN 2 /* oBehParams2ndByte */ #define FISH_SPAWNER_BP_MANY_BLUE 0 #define FISH_SPAWNER_BP_FEW_BLUE 1 @@ -437,6 +437,8 @@ #define YOSHI_ACT_WALK_JUMP_OFF_ROOF 3 #define YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN 4 #define YOSHI_ACT_GIVE_PRESENT 5 + #define YOSHI_ACT_GONE 6 + #define YOSHI_ACT_REAPPEAR 7 #define YOSHI_ACT_CREDITS 10 /* Koopa */ diff --git a/include/object_fields.h b/include/object_fields.h index 11f07257d..fedbe1e91 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -643,7 +643,7 @@ #define /*0x0FC*/ oCameraLakituCircleRadius OBJECT_FIELD_F32(0x1D) #define /*0x100*/ oCameraLakituFinishedDialog OBJECT_FIELD_S32(0x1E) #ifndef VERSION_JP -#define /*0x104*/ oCameraLakituUnk104 OBJECT_FIELD_S32(0x1F) +#define /*0x104*/ oCameraLakituMusicPlayed OBJECT_FIELD_S32(0x1F) #endif #define /*0x1AC*/ oCameraLakituPitchVel OBJECT_FIELD_S16(0x49, 0) #define /*0x1AE*/ oCameraLakituYawVel OBJECT_FIELD_S16(0x49, + 1) diff --git a/src/audio/external.c b/src/audio/external.c index 6cc466ba5..1d5fde0b7 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -297,7 +297,7 @@ const u8 sBackgroundMusicDefaultVolumeDefault[35] = { 80, // SEQ_EVENT_CUTSCENE_VICTORY 70, // SEQ_EVENT_CUTSCENE_ENDING 65, // SEQ_MENU_FILE_SELECT - 0, // SEQ_EVENT_CUTSCENE_LAKITU (not in JP) + 80, // SEQ_EVENT_CUTSCENE_LAKITU (not in JP) }; // Default volume for background music sequences (playing on player 0). @@ -336,7 +336,7 @@ u8 sBackgroundMusicDefaultVolume[MAX_AUDIO_OVERRIDE] = { 80, // SEQ_EVENT_CUTSCENE_VICTORY 70, // SEQ_EVENT_CUTSCENE_ENDING 65, // SEQ_MENU_FILE_SELECT - 0, // SEQ_EVENT_CUTSCENE_LAKITU (not in JP) + 80, // SEQ_EVENT_CUTSCENE_LAKITU (not in JP) 75, // SEQ_??? 75, // SEQ_??? 75, // SEQ_??? @@ -838,27 +838,27 @@ extern f32 *smlua_get_vec3f_for_play_sound(f32 *pos); void play_sound(s32 soundBits, f32 *pos) { MUTEX_LOCK(gAudioThread); - + pos = smlua_get_vec3f_for_play_sound(pos); smlua_call_event_hooks(HOOK_ON_PLAY_SOUND, soundBits, pos, &soundBits); sSoundRequests[sSoundRequestCount].soundBits = soundBits; sSoundRequests[sSoundRequestCount].position = pos; sSoundRequests[sSoundRequestCount].customFreqScale = 0; sSoundRequestCount++; - + MUTEX_UNLOCK(gAudioThread); } void play_sound_with_freq_scale(s32 soundBits, f32* pos, f32 freqScale) { MUTEX_LOCK(gAudioThread); - + pos = smlua_get_vec3f_for_play_sound(pos); smlua_call_event_hooks(HOOK_ON_PLAY_SOUND, soundBits, pos, &soundBits); sSoundRequests[sSoundRequestCount].soundBits = soundBits; sSoundRequests[sSoundRequestCount].position = pos; sSoundRequests[sSoundRequestCount].customFreqScale = freqScale; sSoundRequestCount++; - + MUTEX_UNLOCK(gAudioThread); } @@ -997,13 +997,13 @@ static void delete_sound_from_bank(u8 bank, u8 soundIndex) { */ static void update_background_music_after_sound(u8 bank, u8 soundIndex) { MUTEX_LOCK(gAudioThread); - + if (bank >= SOUND_BANK_COUNT || soundIndex >= SOUND_INDEX_COUNT) { return; } if (sSoundBanks[bank][soundIndex].soundBits & SOUND_LOWER_BACKGROUND_MUSIC) { sSoundBanksThatLowerBackgroundMusic &= (1 << bank) ^ 0xffff; begin_background_music_fade(50); } - + MUTEX_UNLOCK(gAudioThread); } @@ -1779,7 +1779,7 @@ static void update_game_sound(void) { */ static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) { MUTEX_LOCK(gAudioThread); - + if (player >= SEQUENCE_PLAYERS) { return; } u8 targetVolume; u8 i; @@ -1829,7 +1829,7 @@ static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) { */ void seq_player_fade_out(u8 player, u16 fadeDuration) { MUTEX_LOCK(gAudioThread); - + if (player >= SEQUENCE_PLAYERS) { return; } #if defined(VERSION_EU) || defined(VERSION_SH) #ifdef VERSION_EU @@ -1866,7 +1866,7 @@ void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration) { */ static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale, u16 fadeDuration) { MUTEX_LOCK(gAudioThread); - + struct ChannelVolumeScaleFade *temp; if (player >= SEQUENCE_PLAYERS) { return; } if (channelIndex >= CHANNELS_MAX) { return; } @@ -1880,7 +1880,7 @@ static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale temp->target = targetScale; temp->current = gSequencePlayers[player].channels[channelIndex]->volumeScale; } - + MUTEX_UNLOCK(gAudioThread); } @@ -2089,7 +2089,7 @@ void unused_8031FED0(u8 player, u32 bits, s8 arg2) { */ void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage) { MUTEX_LOCK(gAudioThread); - + if (player >= SEQUENCE_PLAYERS) { return; } if (player == SEQ_PLAYER_LEVEL) { sLowerBackgroundMusicVolume = TRUE; @@ -2097,7 +2097,7 @@ void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage) { } else if (gSequencePlayers[player].enabled == TRUE) { seq_player_fade_to_percentage_of_volume(player, fadeDuration, percentage); } - + MUTEX_UNLOCK(gAudioThread); } @@ -2111,7 +2111,7 @@ void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage) { */ void seq_player_unlower_volume(u8 player, u16 fadeDuration) { MUTEX_LOCK(gAudioThread); - + if (player >= SEQUENCE_PLAYERS) { return; } sLowerBackgroundMusicVolume = FALSE; if (player == SEQ_PLAYER_LEVEL) { @@ -2123,7 +2123,7 @@ void seq_player_unlower_volume(u8 player, u16 fadeDuration) { seq_player_fade_to_normal_volume(player, fadeDuration); } } - + MUTEX_UNLOCK(gAudioThread); } @@ -2143,7 +2143,7 @@ static u8 begin_background_music_fade(u16 fadeDuration) { || sCurrentBackgroundMusicSeqId == SEQ_EVENT_CUTSCENE_CREDITS) { return 0xff; } - + MUTEX_LOCK(gAudioThread); if (gSequencePlayers[SEQ_PLAYER_LEVEL].volume == 0.0f && fadeDuration) { @@ -2180,7 +2180,7 @@ static u8 begin_background_music_fade(u16 fadeDuration) { seq_player_fade_to_normal_volume(SEQ_PLAYER_LEVEL, fadeDuration); } } - + MUTEX_UNLOCK(gAudioThread); return targetVolume; @@ -2191,7 +2191,7 @@ static u8 begin_background_music_fade(u16 fadeDuration) { */ void set_audio_muted(u8 muted) { MUTEX_LOCK(gAudioThread); - + u8 i; for (i = 0; i < SEQUENCE_PLAYERS; i++) { @@ -2204,7 +2204,7 @@ void set_audio_muted(u8 muted) { gSequencePlayers[i].muted = muted; #endif } - + MUTEX_UNLOCK(gAudioThread); } @@ -2213,7 +2213,7 @@ void set_audio_muted(u8 muted) { */ void sound_init(void) { MUTEX_LOCK(gAudioThread); - + u8 i; u8 j; @@ -2272,7 +2272,7 @@ void sound_init(void) { sCurrentSecondaryMusicVolume = 0; sNumProcessedSoundRequests = 0; sSoundRequestCount = 0; - + MUTEX_UNLOCK(gAudioThread); } @@ -2303,7 +2303,7 @@ void get_currently_playing_sound(u8 bank, u8 *numPlayingSounds, u8 *numSoundsInB */ void stop_sound(u32 soundBits, f32 *pos) { MUTEX_LOCK(gAudioThread); - + pos = smlua_get_vec3f_for_play_sound(pos); u8 bank = (soundBits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK; if (bank >= SOUND_BANK_COUNT) { return; } @@ -2326,7 +2326,7 @@ void stop_sound(u32 soundBits, f32 *pos) { soundIndex = sSoundBanks[bank][soundIndex].next; } } - + MUTEX_UNLOCK(gAudioThread); } @@ -2335,7 +2335,7 @@ void stop_sound(u32 soundBits, f32 *pos) { */ void stop_sounds_from_source(f32 *pos) { MUTEX_LOCK(gAudioThread); - + pos = smlua_get_vec3f_for_play_sound(pos); u8 bank; u8 soundIndex; @@ -2350,7 +2350,7 @@ void stop_sounds_from_source(f32 *pos) { soundIndex = sSoundBanks[bank][soundIndex].next; } } - + MUTEX_UNLOCK(gAudioThread); } @@ -2359,7 +2359,7 @@ void stop_sounds_from_source(f32 *pos) { */ static void stop_sounds_in_bank(u8 bank) { MUTEX_LOCK(gAudioThread); - + if (bank >= SOUND_BANK_COUNT) { return; } u8 soundIndex = sSoundBanks[bank][0].next; @@ -2368,7 +2368,7 @@ static void stop_sounds_in_bank(u8 bank) { sSoundBanks[bank][soundIndex].soundBits = NO_SOUND; soundIndex = sSoundBanks[bank][soundIndex].next; } - + MUTEX_UNLOCK(gAudioThread); } @@ -2390,7 +2390,7 @@ void stop_sounds_in_continuous_banks(void) { */ void sound_banks_disable(UNUSED u8 player, u16 bankMask) { MUTEX_LOCK(gAudioThread); - + u8 i; for (i = 0; i < SOUND_BANK_COUNT; i++) { @@ -2399,7 +2399,7 @@ void sound_banks_disable(UNUSED u8 player, u16 bankMask) { } bankMask = bankMask >> 1; } - + MUTEX_UNLOCK(gAudioThread); } @@ -2408,13 +2408,13 @@ void sound_banks_disable(UNUSED u8 player, u16 bankMask) { */ static void disable_all_sequence_players(void) { MUTEX_LOCK(gAudioThread); - + u8 i; for (i = 0; i < SEQUENCE_PLAYERS; i++) { sequence_player_disable(&gSequencePlayers[i]); } - + MUTEX_UNLOCK(gAudioThread); } @@ -2423,7 +2423,7 @@ static void disable_all_sequence_players(void) { */ void sound_banks_enable(UNUSED u8 player, u16 bankMask) { MUTEX_LOCK(gAudioThread); - + u8 i; for (i = 0; i < SOUND_BANK_COUNT; i++) { @@ -2432,7 +2432,7 @@ void sound_banks_enable(UNUSED u8 player, u16 bankMask) { } bankMask = bankMask >> 1; } - + MUTEX_UNLOCK(gAudioThread); } @@ -2511,7 +2511,7 @@ void set_sequence_player_volume(s32 player, f32 volume) { */ void play_music(u8 player, u16 seqArgs, u16 fadeTimer) { MUTEX_LOCK(gAudioThread); - + if (player >= SEQUENCE_PLAYERS) { return; } u8 seqId = seqArgs & 0xff; u8 priority = seqArgs >> 8; @@ -2574,7 +2574,7 @@ void play_music(u8 player, u16 seqArgs, u16 fadeTimer) { // Insert item into queue. sBackgroundMusicQueue[foundIndex].priority = priority; sBackgroundMusicQueue[foundIndex].seqId = seqId; - + MUTEX_UNLOCK(gAudioThread); } @@ -2583,7 +2583,7 @@ void play_music(u8 player, u16 seqArgs, u16 fadeTimer) { */ void stop_background_music(u16 seqId) { MUTEX_LOCK(gAudioThread); - + u8 foundIndex; u8 i; @@ -2639,7 +2639,7 @@ void stop_background_music(u16 seqId) { // @bug? If the sequence queue is full and we attempt to stop a sequence // that isn't in the queue, this writes out of bounds. Can that happen? sBackgroundMusicQueue[i].priority = 0; - + MUTEX_UNLOCK(gAudioThread); } @@ -2725,7 +2725,7 @@ void fade_in_env_music(void) { */ void play_secondary_music(u8 seqId, u8 bgMusicVolume, u8 volume, u16 fadeTimer) { MUTEX_LOCK(gAudioThread); - + UNUSED u32 dummy; sUnused80332118 = 0; @@ -2748,7 +2748,7 @@ void play_secondary_music(u8 seqId, u8 bgMusicVolume, u8 volume, u16 fadeTimer) seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, fadeTimer, volume); sCurrentSecondaryMusicVolume = volume; } - + MUTEX_UNLOCK(gAudioThread); } @@ -2770,7 +2770,7 @@ void stop_secondary_music(u16 fadeTimer) { */ void set_audio_fadeout(u16 fadeDuration) { MUTEX_LOCK(gAudioThread); - + if (sHasStartedFadeOut) { return; } @@ -2798,7 +2798,7 @@ void set_audio_fadeout(u16 fadeDuration) { } sHasStartedFadeOut = TRUE; - + MUTEX_UNLOCK(gAudioThread); } @@ -2898,7 +2898,7 @@ void play_toads_jingle(void) { */ void sound_reset(u8 presetId) { MUTEX_LOCK(gAudioThread); - + #ifndef VERSION_JP if (presetId >= 8) { presetId = 0; @@ -2926,7 +2926,7 @@ void sound_reset(u8 presetId) { D_80332108 = (D_80332108 & 0xf0) + presetId; gSoundMode = D_80332108 >> 4; sHasStartedFadeOut = FALSE; - + MUTEX_UNLOCK(gAudioThread); } diff --git a/src/game/behaviors/bowser.inc.c b/src/game/behaviors/bowser.inc.c index 1d7dab87d..dc89a7bd7 100644 --- a/src/game/behaviors/bowser.inc.c +++ b/src/game/behaviors/bowser.inc.c @@ -245,7 +245,7 @@ void bowser_act_intro_walk(void) { } } -static void bowser_debug_actions(void) // unused +UNUSED static void bowser_debug_actions(void) // unused { if (gDebugInfo[5][1] != 0) { o->oAction = D_8032F4FC[gDebugInfo[5][2] & 0xf]; @@ -778,7 +778,7 @@ void bowser_act_thrown_dropped(void) o->oAction = 4; else o->oAction = 12; - + if (is_nearest_mario_state_to_object(gMarioState, o)) { network_send_object(o); } @@ -887,9 +887,9 @@ void bowser_spawn_grand_star_key(void) { reward->oHomeX = reward->oPosX; reward->oHomeY = reward->oPosY; reward->oHomeZ = reward->oPosZ; - + sync_object_set_id(reward); - + struct Object* spawn_objects[] = { reward }; u32 models[] = { MODEL_STAR }; network_send_spawn_objects(spawn_objects, models, 1); @@ -1015,7 +1015,7 @@ u8 bowser_dead_bits_end_continue_dialog(void) { return o->oAction == 4 && o->oBo s32 bowser_dead_bits_end(void) { struct MarioState *marioState = nearest_mario_state_to_object(o); - + if (o->oBowserUnkF8 < 2) { s32 dialogID = gBehaviorValues.dialogs.Bowser3Defeated120StarsDialog; if (gHudDisplay.stars < 120) { @@ -1382,7 +1382,7 @@ void bhv_bowser_override_ownership(u8* shouldOverride, u8* shouldOwn) { *shouldOwn = FALSE; return; } - + // tilting platform static u8 tiltingTimer = 0; if (o->oAction == 19) { tiltingTimer = 5; } @@ -1426,7 +1426,7 @@ void bhv_bowser_init(void) { o->oBowserUnk1AE = 0; o->oBowserEyesShut = 0; bowserCutscenePlayed = FALSE; - + // Make sure we're the first to trigger Bowser. if (!is_other_player_active()) { bowserIsCutscenePlayer = TRUE; @@ -1437,7 +1437,7 @@ void bhv_bowser_init(void) { bowserCutsceneGlobalIndex = UNKNOWN_GLOBAL_INDEX; o->oAction = 20; // bowser_act_nothing } - + if (!sync_object_is_initialized(o->oSyncID)) { struct SyncObject* so = sync_object_init(o, 8000.0f); if (so) { diff --git a/src/game/behaviors/camera_lakitu.inc.c b/src/game/behaviors/camera_lakitu.inc.c index 702d36216..a4ad352fb 100644 --- a/src/game/behaviors/camera_lakitu.inc.c +++ b/src/game/behaviors/camera_lakitu.inc.c @@ -53,15 +53,13 @@ void bhv_camera_lakitu_init(void) { sync_object_init_field(o, o->oCameraLakituFinishedDialog); sync_object_init_field(o, o->oCameraLakituPitchVel); #ifndef VERSION_JP - sync_object_init_field(o, o->oCameraLakituUnk104); + sync_object_init_field(o, o->oCameraLakituMusicPlayed); #endif } } } -static u8 camera_lakitu_intro_act_trigger_cutscene_continue_dialog(void) { - return (o->oAction == CAMERA_LAKITU_INTRO_ACT_TRIGGER_CUTSCENE); -} +u8 camera_lakitu_intro_act_show_dialog_continue_dialog(void) { return o->oCameraLakituFinishedDialog != TRUE; } /** * Wait for mario to stand on the bridge, then interrupt his action and enter @@ -77,21 +75,18 @@ static void camera_lakitu_intro_act_trigger_cutscene(void) { if (player->oPosX > -544.0f && player->oPosX < 545.0f && player->oPosY > 800.0f && player->oPosZ > -2000.0f && player->oPosZ < -177.0f) { - if (should_start_or_continue_dialog(marioState, o) && set_mario_npc_dialog(&gMarioStates[0], 2, camera_lakitu_intro_act_trigger_cutscene_continue_dialog) == 1) { + if (should_start_or_continue_dialog(marioState, o) && set_mario_npc_dialog(&gMarioStates[0], 2, camera_lakitu_intro_act_show_dialog_continue_dialog) == 1) { o->oAction = CAMERA_LAKITU_INTRO_ACT_SPAWN_CLOUD; } } } -static u8 camera_lakitu_intro_act_spawn_cloud_continue_dialog(void) { - return (o->oAction == CAMERA_LAKITU_INTRO_ACT_SPAWN_CLOUD); -} /** * Warp up into the air and spawn cloud, then enter the TODO action. */ static void camera_lakitu_intro_act_spawn_cloud(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState && should_start_or_continue_dialog(marioState, o) && set_mario_npc_dialog(&gMarioStates[0], 2, camera_lakitu_intro_act_spawn_cloud_continue_dialog) == 2) { + if (marioState && should_start_or_continue_dialog(marioState, o) && set_mario_npc_dialog(&gMarioStates[0], 2, camera_lakitu_intro_act_show_dialog_continue_dialog) == 2) { o->oAction = CAMERA_LAKITU_INTRO_ACT_UNK2; o->oPosX = 1800.0f; @@ -106,8 +101,6 @@ static void camera_lakitu_intro_act_spawn_cloud(void) { } } -u8 camera_lakitu_intro_act_show_dialog_continue_dialog(void) { return o->oCameraLakituFinishedDialog != TRUE; } - /** * Circle down to mario, show the dialog, then fly away. */ @@ -131,6 +124,8 @@ static void camera_lakitu_intro_act_show_dialog(void) { } o->oFaceAngleYaw = angleToPlayer; + should_start_or_continue_dialog(marioState, o); + // After finishing dialog, fly away and despawn if (o->oCameraLakituFinishedDialog) { approach_f32_ptr(&o->oCameraLakituSpeed, 60.0f, 3.0f); @@ -167,9 +162,9 @@ static void camera_lakitu_intro_act_show_dialog(void) { approach_f32_ptr(&o->oCameraLakituCircleRadius, 200.0f, 50.0f); if (distanceToPlayer < 1000.0f) { #ifndef VERSION_JP - if (!o->oCameraLakituUnk104) { + if (!o->oCameraLakituMusicPlayed) { play_music(SEQ_PLAYER_LEVEL, SEQUENCE_ARGS(15, SEQ_EVENT_CUTSCENE_LAKITU), 0); - o->oCameraLakituUnk104 = TRUE; + o->oCameraLakituMusicPlayed = TRUE; } #endif diff --git a/src/game/behaviors/spawn_star.inc.c b/src/game/behaviors/spawn_star.inc.c index 71783e743..f58f1d93d 100644 --- a/src/game/behaviors/spawn_star.inc.c +++ b/src/game/behaviors/spawn_star.inc.c @@ -91,7 +91,7 @@ void bhv_star_spawn_init(void) { o->oForwardVel = o->oStarSpawnDisFromHome / 30.0f; o->oStarSpawnUnkFC = o->oPosY; - if (o->oStarSpawnExtCutsceneFlags && ((gMarioStates[0].action & ACT_GROUP_MASK) != ACT_GROUP_CUTSCENE)) { + if (o->oStarSpawnExtCutsceneFlags) { if (o->oBehParams2ndByte == 0 || gCurrCourseNum == COURSE_BBH) cutscene_object(CUTSCENE_STAR_SPAWN, o); else diff --git a/src/game/behaviors/ukiki.inc.c b/src/game/behaviors/ukiki.inc.c index 94124d606..11caa0660 100644 --- a/src/game/behaviors/ukiki.inc.c +++ b/src/game/behaviors/ukiki.inc.c @@ -531,7 +531,7 @@ void ukiki_free_loop(void) { * * Possibly unused so AnimState could be used for wearing a cap? */ -static void ukiki_blink_timer(void) { +UNUSED static void ukiki_blink_timer(void) { if (gGlobalTimer % 50 < 7) { o->oAnimState = UKIKI_ANIM_STATE_EYE_CLOSED; } else { diff --git a/src/game/behaviors/water_ring.inc.c b/src/game/behaviors/water_ring.inc.c index 07e69e8cb..b088ae08a 100644 --- a/src/game/behaviors/water_ring.inc.c +++ b/src/game/behaviors/water_ring.inc.c @@ -48,7 +48,9 @@ void bhv_jet_stream_water_ring_init(void) { // sp2c = ringManager void water_ring_check_collection(f32 avgScale, struct Object *ringManager) { - struct Object* player = nearest_player_to_object(o); + struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return; } + struct Object* player = marioState->marioObj; if (!player) { return; } f32 marioDistInFront = water_ring_calc_mario_dist(); struct Object *ringSpawner; @@ -75,6 +77,9 @@ void water_ring_check_collection(f32 avgScale, struct Object *ringManager) { + (((u8) ringSpawner->oWaterRingSpawnerRingsCollected - 1) << 16), gGlobalSoundSource); #endif + if (ringSpawner->oWaterRingSpawnerRingsCollected == 5) { + ringSpawner->globalPlayerIndex = gNetworkPlayers[marioState->playerIndex].globalIndex; + } } ringManager->oWaterRingMgrLastRingCollected = o->oWaterRingIndex; @@ -196,7 +201,7 @@ void bhv_jet_stream_ring_spawner_loop(void) { case JS_RING_SPAWNER_ACT_ACTIVE: water_ring_spawner_act_inactive(); - if (o->oWaterRingSpawnerRingsCollected == 5) { + if (o->oWaterRingSpawnerRingsCollected == 5 && o->globalPlayerIndex == gNetworkPlayerLocal->globalIndex) { spawn_mist_particles(); f32* starPos = gLevelValues.starPositions.JetstreamRingStarPos; diff --git a/src/game/behaviors/yoshi.inc.c b/src/game/behaviors/yoshi.inc.c index 3bcf898c8..2764204cb 100644 --- a/src/game/behaviors/yoshi.inc.c +++ b/src/game/behaviors/yoshi.inc.c @@ -4,48 +4,69 @@ // Note that this doesn't contain the Y coordinate since the castle roof is flat, // so o->oHomeY is never updated. static s16 sYoshiHomeLocations[] = { 0, -5625, -1364, -5912, -1403, -4609, -1004, -5308 }; +static s16 sYoshiRespawnPos[] = { -12406, 1076, -8567 }; +static u8 sYoshiRespawnDuration = 2 * 30; static u8 sYoshiTalkingState = 0; +static bool sYoshiNeeded = false; + +extern void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 padding); static u8 yoshi_talk_loop_continue_dialog(void) { - return sYoshiTalkingState == 0; + return sYoshiTalkingState == 0 || sYoshiTalkingState == 1; +} + +void bhv_yoshi_override_ownership(u8* shouldOverride, u8* shouldOwn) { + *shouldOverride = o->oAction == YOSHI_ACT_TALK; + *shouldOwn = false; + if (*shouldOverride) { + *shouldOwn = (gNetworkPlayerLocal->globalIndex == o->globalPlayerIndex); + } } void bhv_yoshi_init(void) { + sOverrideYoshiAlive = false; sYoshiTalkingState = 0; o->oGravity = 2.0f; o->oFriction = 0.9f; o->oBuoyancy = 1.3f; o->oInteractionSubtype = INT_SUBTYPE_NPC; - if (save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) < 120 - || sYoshiDead == TRUE) { - o->activeFlags = ACTIVE_FLAG_DEACTIVATED; + if (save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) < 120) { + o->oAction = YOSHI_ACT_GONE; } - sync_object_init(o, 4000.0f); - sync_object_init_field(o, o->oYoshiBlinkTimer); - sync_object_init_field(o, o->oYoshiChosenHome); - sync_object_init_field(o, o->oYoshiTargetYaw); - sync_object_init_field(o, o->oHomeX); - sync_object_init_field(o, o->oHomeY); - sync_object_init_field(o, o->oHomeZ); + struct SyncObject* so = sync_object_init(o, 4000.0f); + if (so != NULL) { + so->override_ownership = bhv_yoshi_override_ownership; + sync_object_init_field(o, o->oYoshiBlinkTimer); + sync_object_init_field(o, o->oYoshiChosenHome); + sync_object_init_field(o, o->oYoshiTargetYaw); + sync_object_init_field(o, o->oHomeX); + sync_object_init_field(o, o->oHomeY); + sync_object_init_field(o, o->oHomeZ); + sync_object_init_field(o, o->oAction); + sync_object_init_field(o, o->globalPlayerIndex); + } } void yoshi_walk_loop(void) { - UNUSED s16 sp26; - s16 sp24 = o->header.gfx.animInfo.animFrame; + sYoshiTalkingState = 0; + cur_obj_become_tangible(); + s16 animFrame = o->header.gfx.animInfo.animFrame; o->oForwardVel = 10.0f; - sp26 = object_step(); + object_step(); o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oYoshiTargetYaw, 0x500); if (is_point_close_to_object(o, o->oHomeX, 3174.0f, o->oHomeZ, 200)) o->oAction = YOSHI_ACT_IDLE; cur_obj_init_animation(1); - if (sp24 == 0 || sp24 == 15) + if (animFrame == 0 || animFrame == 15) cur_obj_play_sound_2(SOUND_GENERAL_YOSHI_WALK); - if (o->oInteractStatus == INT_STATUS_INTERACTED && sYoshiTalkingState == 0) { + if (o->oInteractStatus == INT_STATUS_INTERACTED) { + struct MarioState* marioState = nearest_mario_state_to_object(o); + o->globalPlayerIndex = gNetworkPlayers[marioState->playerIndex].globalIndex; o->oAction = YOSHI_ACT_TALK; } @@ -56,8 +77,9 @@ void yoshi_walk_loop(void) { } void yoshi_idle_loop(void) { + sYoshiTalkingState = 0; + cur_obj_become_tangible(); s16 chosenHome; - UNUSED s16 sp1C = o->header.gfx.animInfo.animFrame; if (o->oTimer > 90) { chosenHome = random_float() * 3.99; @@ -75,7 +97,9 @@ void yoshi_idle_loop(void) { } cur_obj_init_animation(0); - if (o->oInteractStatus == INT_STATUS_INTERACTED && sYoshiTalkingState == 0) { + if (o->oInteractStatus == INT_STATUS_INTERACTED) { + struct MarioState* marioState = nearest_mario_state_to_object(o); + o->globalPlayerIndex = gNetworkPlayers[marioState->playerIndex].globalIndex; o->oAction = YOSHI_ACT_TALK; } @@ -91,32 +115,50 @@ void yoshi_idle_loop(void) { } void yoshi_talk_loop(void) { - struct MarioState* marioState = nearest_mario_state_to_object(o); + cur_obj_become_intangible(); + sYoshiTalkingState = 1; + push_mario_out_of_object(&gMarioStates[0], o, -10.0f); + struct NetworkPlayer* np = network_player_from_global_index(o->globalPlayerIndex); + struct MarioState* marioState = &gMarioStates[np->localIndex]; struct Object* player = marioState ? marioState->marioObj : NULL; s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; - if (marioState != &gMarioStates[0]) { + if (np->localIndex != 0) { + cur_obj_init_animation((s16) o->oMoveAngleYaw == angleToPlayer ? 0 : 1); return; } if ((s16) o->oMoveAngleYaw == angleToPlayer) { - if (sYoshiTalkingState == 0) { - play_puzzle_jingle(); - sYoshiTalkingState = 1; + cur_obj_init_animation(0); + if (set_mario_npc_dialog(&gMarioStates[0], 1, yoshi_talk_loop_continue_dialog) == 2) { + if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, gBehaviorValues.dialogs.YoshiDialog)) { + o->oInteractStatus = 0; + o->oHomeX = sYoshiHomeLocations[2]; + o->oHomeZ = sYoshiHomeLocations[3]; + o->oYoshiTargetYaw = atan2s(o->oHomeZ - o->oPosZ, o->oHomeX - o->oPosX); + o->oAction = YOSHI_ACT_GIVE_PRESENT; + } } } else { cur_obj_init_animation(1); + play_puzzle_jingle(); o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, angleToPlayer, 0x500); } } void yoshi_walk_and_jump_off_roof_loop(void) { - s16 sp26 = o->header.gfx.animInfo.animFrame; + push_mario_out_of_object(&gMarioStates[0], o, -10.0f); + cur_obj_become_intangible(); + s16 animFrame = o->header.gfx.animInfo.animFrame; o->oForwardVel = 10.0f; object_step(); cur_obj_init_animation(1); - if (o->oTimer == 0) + if (o->oTimer == 0 + && o->globalPlayerIndex == gNetworkPlayerLocal->globalIndex + && gMarioStates[0].interactObj == o + && (gMarioStates[0].action == ACT_READING_NPC_DIALOG + || gMarioStates[0].action == ACT_WAITING_FOR_DIALOG)) cutscene_object(CUTSCENE_STAR_SPAWN, o); o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oYoshiTargetYaw, 0x500); @@ -129,36 +171,101 @@ void yoshi_walk_and_jump_off_roof_loop(void) { o->oAction = YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN; } - if (sp26 == 0 || sp26 == 15) { + if (animFrame == 0 || animFrame == 15) { cur_obj_play_sound_2(SOUND_GENERAL_YOSHI_WALK); } } void yoshi_finish_jumping_and_despawn_loop(void) { + push_mario_out_of_object(&gMarioStates[0], o, -10.0f); + cur_obj_become_intangible(); cur_obj_extend_animation_if_at_end(); obj_move_xyz_using_fvel_and_yaw(o); o->oVelY -= 2.0; if (o->oPosY < 2100.0f) { - set_mario_npc_dialog(&gMarioStates[0], 0, yoshi_talk_loop_continue_dialog); + sYoshiTalkingState = 2; gObjCutsceneDone = TRUE; - sYoshiDead = TRUE; - o->activeFlags = ACTIVE_FLAG_DEACTIVATED; + o->oAction = YOSHI_ACT_GONE; } } void yoshi_give_present_loop(void) { - s32 sp1C = gGlobalTimer; + cur_obj_become_intangible(); + push_mario_out_of_object(&gMarioStates[0], o, -10.0f); + if (gNetworkPlayerLocal->globalIndex == o->globalPlayerIndex) { + if (gHudDisplay.lives == 100) { + play_sound(SOUND_GENERAL_COLLECT_1UP, gGlobalSoundSource); + gMarioStates[0].specialTripleJump = true; + if (sYoshiNeeded) { + sYoshiTalkingState = 2; + o->oAction = YOSHI_ACT_IDLE; + } else { + o->oAction = YOSHI_ACT_WALK_JUMP_OFF_ROOF; + } + return; + } - if (gHudDisplay.lives == 100) { - play_sound(SOUND_GENERAL_COLLECT_1UP, gGlobalSoundSource); - gMarioStates[0].specialTripleJump = true; - o->oAction = YOSHI_ACT_WALK_JUMP_OFF_ROOF; + if ((gGlobalTimer & 0x03) == 0) { + play_sound(SOUND_MENU_YOSHI_GAIN_LIVES, gGlobalSoundSource); + gMarioState->numLives++; + } + } +} + +void yoshi_gone(void) { + cur_obj_become_intangible(); + cur_obj_hide(); +} + +void yoshi_reappear(void) { + if (gCurrLevelNum != LEVEL_CASTLE_GROUNDS || !dynos_level_is_vanilla_level(gCurrLevelNum)) { + o->oHomeX = sYoshiHomeLocations[2]; + o->oHomeY = 3174.0f; + o->oHomeZ = sYoshiHomeLocations[3]; + o->oPosX = o->oHomeX; + o->oPosY = o->oHomeY; + o->oPosZ = o->oHomeZ; + o->oForwardVel = 0.0f; + o->oVelY = 0.0f; + cur_obj_init_animation(0); + spawn_mist_particles(); + cur_obj_play_sound_2(SOUND_GENERAL_YOSHI_WALK); + o->oAction = YOSHI_ACT_IDLE; return; } - if ((sp1C & 0x03) == 0) { - play_sound(SOUND_MENU_YOSHI_GAIN_LIVES, gGlobalSoundSource); - gMarioState->numLives++; + u8 decAmount = 4; + if (o->oTimer == 0) { + o->oHomeX = sYoshiHomeLocations[2]; + o->oHomeY = 3174.0f; + o->oHomeZ = sYoshiHomeLocations[3]; + o->oPosX = sYoshiRespawnPos[0]; + o->oPosY = sYoshiRespawnPos[1]; + o->oPosZ = sYoshiRespawnPos[2]; + cur_obj_init_animation(2); + cur_obj_play_sound_2(SOUND_GENERAL_ENEMY_ALERT1); + spawn_mist_particles(); + o->oVelY = 160; + } + s16 dx = o->oHomeX - sYoshiRespawnPos[0]; + s16 dz = o->oHomeZ - sYoshiRespawnPos[2]; + s16 distXZ = sqrtf(dx * dx + dz * dz); + o->oForwardVel = distXZ / sYoshiRespawnDuration; + o->oVelY -= decAmount; + o->oMoveAngleYaw = cur_obj_angle_to_home(); + obj_move_xyz_using_fvel_and_yaw(o); + cur_obj_extend_animation_if_at_end(); + if (o->oPosY < o->oHomeY && o->oVelY < 0) { o->oPosY = o->oHomeY; } + if (o->oTimer >= sYoshiRespawnDuration) { + o->oPosX = o->oHomeX; + o->oPosY = 3174.0f; + o->oPosZ = o->oHomeZ; + cur_obj_init_animation(0); + spawn_mist_particles(); + cur_obj_play_sound_2(SOUND_GENERAL_YOSHI_WALK); + o->oForwardVel = 0.0f; + o->oVelY = 0.0f; + o->oAction = YOSHI_ACT_IDLE; } } @@ -188,58 +295,56 @@ void bhv_yoshi_loop(void) { yoshi_give_present_loop(); break; + case YOSHI_ACT_GONE: + yoshi_gone(); + break; + + case YOSHI_ACT_REAPPEAR: + yoshi_reappear(); + break; + case YOSHI_ACT_CREDITS: cur_obj_init_animation(0); break; } - switch (sYoshiTalkingState) { - case 1: - cur_obj_init_animation(0); - if (set_mario_npc_dialog(&gMarioStates[0], 1, yoshi_talk_loop_continue_dialog) == 2) { - sYoshiTalkingState = 2; - } - break; - - case 2: - if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, gBehaviorValues.dialogs.YoshiDialog)) { - sYoshiTalkingState = 3; - o->oInteractStatus = 0; - o->oHomeX = sYoshiHomeLocations[2]; - o->oHomeZ = sYoshiHomeLocations[3]; - o->oYoshiTargetYaw = atan2s(o->oHomeZ - o->oPosZ, o->oHomeX - o->oPosX); - o->oAction = YOSHI_ACT_WALK; - } - break; - - case 3: - o->oInteractStatus = 0; - break; - - default: - break; + // sanity check reading dialog + if (gMarioStates[0].interactObj == o + && gNetworkPlayerLocal->globalIndex != o->globalPlayerIndex + && o->oAction != YOSHI_ACT_IDLE + && o->oAction != YOSHI_ACT_WALK + && (gMarioStates[0].action == ACT_READING_NPC_DIALOG + || gMarioStates[0].action == ACT_WAITING_FOR_DIALOG)) { + set_mario_action(&gMarioStates[0], ACT_IDLE, 0); } - if (sYoshiTalkingState > 0) { - extern void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 padding); - push_mario_out_of_object(&gMarioStates[0], o, -10.0f); - } - - if (sYoshiTalkingState > 2) { - if (gHudDisplay.lives >= 100) { - gMarioStates[0].specialTripleJump = true; - sYoshiTalkingState = 3; - } else if ((gGlobalTimer & 0x03) == 0) { - play_sound(SOUND_MENU_YOSHI_GAIN_LIVES, gGlobalSoundSource); - gMarioStates[0].numLives++; + if (sOverrideYoshiAlive) { + sYoshiNeeded = true; + } else if (save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) < 120) { + sYoshiNeeded = false; + } else { + sYoshiNeeded = false; + for (u8 i = 0; i < MAX_PLAYERS; i++) { + if (gNetworkPlayers[i].currLevelNum == LEVEL_CASTLE_GROUNDS && !gMarioStates[i].specialTripleJump) { + sYoshiNeeded = true; + break; + } } } - if (gMarioStates[0].action == ACT_WAITING_FOR_DIALOG) { - if (gMarioStates[0].interactObj == o) { - set_mario_action(&gMarioStates[0], ACT_IDLE, 0); - o->oInteractStatus = 0; - } + if (!sYoshiNeeded + && o->oAction != YOSHI_ACT_GONE + && o->oAction != YOSHI_ACT_WALK_JUMP_OFF_ROOF + && o->oAction != YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN + && o->oAction != YOSHI_ACT_REAPPEAR) { + o->oAction = YOSHI_ACT_WALK_JUMP_OFF_ROOF; + } else if (sYoshiNeeded && o->oAction == YOSHI_ACT_GONE) { + o->oAction = YOSHI_ACT_REAPPEAR; } + + if (o->oAction != YOSHI_ACT_GONE) { + cur_obj_unhide(); + } + curr_obj_random_blink(&o->oYoshiBlinkTimer); } diff --git a/src/game/level_update.c b/src/game/level_update.c index 76348da45..f568df29f 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -1938,7 +1938,6 @@ s32 lvl_init_from_save_file(UNUSED s16 arg0, s16 levelNum) { disable_warp_checkpoint(); save_file_move_cap_to_default_location(); select_mario_cam_mode(); - set_yoshi_as_not_dead(); return levelNum; } @@ -2028,7 +2027,6 @@ void fake_lvl_init_from_save_file(void) { disable_warp_checkpoint(); save_file_move_cap_to_default_location(); select_mario_cam_mode(); - set_yoshi_as_not_dead(); fadeout_music(30); gChangeLevel = gLevelValues.entryLevel; diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 293079dc4..98518bad9 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -236,13 +236,6 @@ s32 geo_switch_peach_eyes(s32 run, struct GraphNode *node, UNUSED s32 a2) { return 0; } -// unused -static void stub_is_textbox_active(u16 *a0) { - if (get_dialog_id() == DIALOG_NONE) { - *a0 = 0; - } -} - /** * get_star_collection_dialog: Determine what dialog should show when Mario * collects a star. @@ -1278,6 +1271,7 @@ s32 act_spawn_spin_airborne(struct MarioState *m) { if (m == &gMarioStates[0]) { load_level_init_text(0); } + m->freeze = 2; return set_water_plunge_action(m); } @@ -1310,6 +1304,7 @@ s32 act_spawn_spin_landing(struct MarioState *m) { if (m == &gMarioStates[0]) { load_level_init_text(0); } + m->freeze = 2; set_mario_action(m, ACT_IDLE, 0); } return FALSE; @@ -1562,6 +1557,7 @@ s32 act_spawn_no_spin_landing(struct MarioState *m) { if (m == &gMarioStates[0]) { load_level_init_text(0); } + m->freeze = 2; set_mario_action(m, ACT_IDLE, 0); } return FALSE; @@ -2191,7 +2187,7 @@ static s32 act_intro_cutscene(struct MarioState *m) { return FALSE; } -static void jumbo_star_offset(struct MarioState* m) { +UNUSED static void jumbo_star_offset(struct MarioState* m) { if (!m) { return; } m->pos[0] += 300.0f * sins(m->faceAngle[1] + 0x4000 * m->playerIndex); m->pos[2] += 300.0f * coss(m->faceAngle[1] + 0x4000 * m->playerIndex); diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index 9af5339af..fc38d0a15 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -73,13 +73,13 @@ static s8 sOrientObjWithFloor = TRUE; s16 sPrevCheckMarioRoom = 0; /** - * Tracks whether or not Yoshi has walked/jumped off the roof. + * Override for whether or not Yoshi has walked/jumped off the roof. */ -s8 sYoshiDead = FALSE; +s8 sOverrideYoshiAlive = FALSE; -/* |description|Resets Yoshi as being alive|descriptionEnd| */ +/* |description|Marks Yoshi as alive|descriptionEnd| */ void set_yoshi_as_not_dead(void) { - sYoshiDead = FALSE; + sOverrideYoshiAlive = FALSE; } /** diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 694fc800f..e31f8f790 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -1736,11 +1736,11 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = { { "oCameraLakituBlinkTimer", LVT_S32, offsetof(struct Object, oCameraLakituBlinkTimer), false, LOT_NONE, 1, sizeof(s32) }, { "oCameraLakituCircleRadius", LVT_F32, offsetof(struct Object, oCameraLakituCircleRadius), false, LOT_NONE, 1, sizeof(f32) }, { "oCameraLakituFinishedDialog", LVT_S32, offsetof(struct Object, oCameraLakituFinishedDialog), false, LOT_NONE, 1, sizeof(s32) }, +#ifndef VERSION_JP + { "oCameraLakituMusicPlayed", LVT_S32, offsetof(struct Object, oCameraLakituMusicPlayed), false, LOT_NONE, 1, sizeof(s32) }, +#endif { "oCameraLakituPitchVel", LVT_S16, offsetof(struct Object, oCameraLakituPitchVel), false, LOT_NONE, 1, sizeof(s16) }, { "oCameraLakituSpeed", LVT_F32, offsetof(struct Object, oCameraLakituSpeed), false, LOT_NONE, 1, sizeof(f32) }, -#ifndef VERSION_JP - { "oCameraLakituUnk104", LVT_S32, offsetof(struct Object, oCameraLakituUnk104), false, LOT_NONE, 1, sizeof(s32) }, -#endif { "oCameraLakituYawVel", LVT_S16, offsetof(struct Object, oCameraLakituYawVel), false, LOT_NONE, 1, sizeof(s16) }, { "oCannonBarrelBubblesUnkF4", LVT_F32, offsetof(struct Object, oCannonBarrelBubblesUnkF4), false, LOT_NONE, 1, sizeof(f32) }, { "oCannonPlayerIndex", LVT_S32, offsetof(struct Object, oCannonPlayerIndex), false, LOT_NONE, 1, sizeof(s32) }, diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 4fe9867df..aa11caa9b 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -2632,6 +2632,8 @@ char gSmluaConstants[] = "" "YOSHI_ACT_WALK_JUMP_OFF_ROOF=3\n" "YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN=4\n" "YOSHI_ACT_GIVE_PRESENT=5\n" +"YOSHI_ACT_GONE=6\n" +"YOSHI_ACT_REAPPEAR=7\n" "YOSHI_ACT_CREDITS=10\n" "KOOPA_UNSHELLED_ACT_RUN=0\n" "KOOPA_UNSHELLED_ACT_DIVE=1\n" diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 8ac087643..78af5534d 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -18017,6 +18017,26 @@ int smlua_func_stuck_in_ground_handler(lua_State* L) { return 1; } +/* +int smlua_func_jumbo_star_offset(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "jumbo_star_offset", 1, top); + return 0; + } + + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIOSTATE); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "jumbo_star_offset"); return 0; } + + extern UNUSED static void jumbo_star_offset(struct MarioState* m); + UNIMPLEMENTED -->(L, jumbo_star_offset(m)); + + return 1; +} +*/ + int smlua_func_generate_yellow_sparkles(lua_State* L) { if (L == NULL) { return 0; } @@ -37921,6 +37941,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "common_death_handler", smlua_func_common_death_handler); smlua_bind_function(L, "launch_mario_until_land", smlua_func_launch_mario_until_land); smlua_bind_function(L, "stuck_in_ground_handler", smlua_func_stuck_in_ground_handler); + //smlua_bind_function(L, "jumbo_star_offset", smlua_func_jumbo_star_offset); <--- UNIMPLEMENTED smlua_bind_function(L, "generate_yellow_sparkles", smlua_func_generate_yellow_sparkles); smlua_bind_function(L, "mario_execute_cutscene_action", smlua_func_mario_execute_cutscene_action); diff --git a/src/pc/network/packets/packet_level.c b/src/pc/network/packets/packet_level.c index aa636f2d9..eab22bb60 100644 --- a/src/pc/network/packets/packet_level.c +++ b/src/pc/network/packets/packet_level.c @@ -4,6 +4,7 @@ #include "game/interaction.h" #include "game/level_update.h" #include "game/ingame_menu.h" +#include "course_table.h" #include "behavior_table.h" #include "object_constants.h" #include "object_fields.h" @@ -79,7 +80,9 @@ void network_receive_level(struct Packet* p) { packet_read(p, &gMarioStates[0].numCoins, sizeof(s16)); packet_read(p, &gPssSlideStarted, sizeof(u8)); packet_read(p, &gTTCSpeedSetting, sizeof(s16)); - gHudDisplay.coins = gMarioStates[0].numCoins; + if (gCurrCourseNum != COURSE_NONE) { + gHudDisplay.coins = gMarioStates[0].numCoins; + } // fix TTC objects by reinitializing values pertaining to speed if (levelNum == LEVEL_TTC) { diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c index 793def2db..b43be91f5 100644 --- a/src/pc/network/packets/packet_player.c +++ b/src/pc/network/packets/packet_player.c @@ -50,6 +50,7 @@ struct PacketPlayerData { u8 framesSinceB; u8 wallKickTimer; u8 doubleJumpTimer; + u8 specialTripleJump; Vec3s faceAngle; Vec3s angleVel; s16 slideYaw; @@ -120,6 +121,7 @@ static void read_packet_data(struct PacketPlayerData* data, struct MarioState* m data->framesSinceB = m->framesSinceB; data->wallKickTimer = m->wallKickTimer; data->doubleJumpTimer = m->doubleJumpTimer; + data->specialTripleJump = m->specialTripleJump; memcpy(data->faceAngle, m->faceAngle, sizeof(s16) * 3); memcpy(data->angleVel, m->angleVel, sizeof(s16) * 3); data->slideYaw = m->slideYaw; @@ -185,6 +187,7 @@ static void write_packet_data(struct PacketPlayerData* data, struct MarioState* m->framesSinceB = data->framesSinceB; m->wallKickTimer = data->wallKickTimer; m->doubleJumpTimer = data->doubleJumpTimer; + m->specialTripleJump = data->specialTripleJump; memcpy(m->faceAngle, data->faceAngle, sizeof(s16) * 3); memcpy(m->angleVel, data->angleVel, sizeof(s16) * 3); m->slideYaw = data->slideYaw;